PageRenderTime 53ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/wrfv2_fire/external/io_grib1/MEL_grib1/gbyte.c

http://github.com/jbeezley/wrf-fire
C | 533 lines | 224 code | 30 blank | 279 comment | 8 complexity | 54250d7c9af4c9ba6b5ed376449702ae MD5 | raw file
Possible License(s): AGPL-1.0
  1. /* gbyte.c:
  2. ADAPTED FROM THE ORIGINAL FORTRAN VERSION OF GBYTE BY:
  3. DR. ROBERT C. GAMMILL, CONSULTANT
  4. NATIONAL CENTER FOR ATMOSPHERIC RESEARCH
  5. MAY 1972
  6. CHANGES FOR FORTRAN 90
  7. AUGUST 1990 RUSSELL E. JONES
  8. NATIONAL WEATHER SERVICE
  9. GBYTE RUN WITHOUT CHANGES ON THE FOLLOWING COMPILERS
  10. MICROSOFT FORTRAN 5.0 OPTIMIZING COMPILER
  11. SVS 32 386 FORTRAN 77 VERSION V2.8.1B
  12. SUN FORTRAN 1.3, 1.4
  13. DEC VAX FORTRAN
  14. SILICONGRAPHICS 3.3, 3.4 FORTRAN 77
  15. IBM370 VS COMPILER
  16. INTERGRAPH GREEN HILLS FORTRAN CLIPPER 1.8.4B
  17. */
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include "dprints.h" /* debug prints & func prototypes */
  21. #include "gribfuncs.h" /* prototypes */
  22. #include "isdb.h" /* WORD_BIT_CNT defn */
  23. /* Added by Todd Hutchinson, 8/10/05*/
  24. /*
  25. * gbyte requires the word bit count to be 32. In order for this to work
  26. * on platforms with 8 byte longs, we must set WORD_BIT_CNT to 32 for
  27. * gbyte.
  28. */
  29. #ifdef WORD_BIT_CNT
  30. #undef WORD_BIT_CNT
  31. #endif
  32. #define WORD_BIT_CNT 32 /* gbyte.c requires the word bit count to be 32! */
  33. /*
  34. *
  35. *****************************************************************
  36. * A. FUNCTION: gbyte
  37. * extracts data of specified length from the specified offset
  38. * from beginning of the given Data block.
  39. *
  40. * INTERFACE:
  41. * void gbyte (inchar, iout, iskip, nbits)
  42. *
  43. * ARGUMENTS (I=input, O=output, I&O=input and output):
  44. * (I) char *inchar;
  45. * The fullword in memory from which unpacking is to
  46. * begin, successive fullwords will be fetched as required.
  47. * (O) unsigned long *iout;
  48. * The value read from in memory that's returned.
  49. * (I&O) unsigned long *iskip;
  50. * a fullword integer specifying the inital offset
  51. * in bits of the first byte, counted from the
  52. * leftmost bit in Inchar. Gets updated upon exit;
  53. * (I) unsigned long nbits;
  54. * a fullword integer specifying the number of bits
  55. * in each byte to be unpacked. Legal byte widths
  56. * are in the range 1 - 32, bytes of width less than 32
  57. * will be right justified in the low-order positions
  58. * of the unpacked fullwords with high-order zero fill.
  59. *
  60. * RETURN CODE: none;
  61. *****************************************************************
  62. *
  63. */
  64. #if PROTOTYPE_NEEDED
  65. void gbyte (char *inchar, unsigned long *iout, unsigned long *iskip,
  66. unsigned long nbits)
  67. #else
  68. void gbyte (inchar, iout, iskip, nbits)
  69. char *inchar; /* input */
  70. unsigned long *iout; /* output, is the value returned */
  71. unsigned long *iskip; /* input, gets updated */
  72. unsigned long nbits; /* input */
  73. #endif
  74. {
  75. long masks[32];
  76. long icon,index,ii,mover,movel;
  77. unsigned long temp, mask, inlong;
  78. /*
  79. * A.1 INITIALIZE mask possibilities of all bits set from LSB to
  80. * a particular bit position; !bit position range: 0 to 31
  81. */
  82. masks[0] = 1;
  83. masks[1] = 3;
  84. masks[2] = 7;
  85. masks[3] = 15;
  86. masks[4] = 31;
  87. masks[5] = 63;
  88. masks[6] = 127;
  89. masks[7] = 255;
  90. masks[8] = 511;
  91. masks[9] = 1023;
  92. masks[10] = 2047;
  93. masks[11] = 4095;
  94. masks[12] = 8191;
  95. masks[13] = 16383;
  96. masks[14] = 32767;
  97. masks[15] = 65535;
  98. masks[16] = 131071;
  99. masks[17] = 262143;
  100. masks[18] = 524287;
  101. masks[19] = 1048575;
  102. masks[20] = 2097151;
  103. masks[21] = 4194303;
  104. masks[22] = 8388607;
  105. masks[23] = 16777215;
  106. masks[24] = 33554431;
  107. masks[25] = 67108863;
  108. masks[26] = 134217727;
  109. masks[27] = 268435455;
  110. masks[28] = 536870911;
  111. masks[29] = 1073741823;
  112. masks[30] = 2147483647;
  113. masks[31] = -1;
  114. /* NBYTE MUST BE LESS THAN OR EQUAL TO WORD_BIT_CNT
  115. *
  116. * A.2 IF (trying to retrieve more than numbits_perword) THEN !here, 32
  117. * RETURN
  118. * ENDIF
  119. */
  120. icon = WORD_BIT_CNT - nbits;
  121. if ( icon < 0 )
  122. {
  123. return;
  124. }
  125. /*
  126. *
  127. * A.3 SET up mask needed for specified #bits to retrieve
  128. */
  129. mask = masks[nbits-1];
  130. /*
  131. *
  132. * A.4 CALCULATE Index !Byte offset from 'inchar' where retrieval begins
  133. */
  134. index = *iskip / WORD_BIT_CNT;
  135. /*
  136. *
  137. * A.5 CALCULATE Bit position within byte Index where retrieval begins
  138. */
  139. ii = *iskip % WORD_BIT_CNT;
  140. /*
  141. *
  142. * A.6 CALCULATE #times to Right-shift the retrieved data so it
  143. * is right adjusted
  144. */
  145. mover = icon - ii;
  146. /*
  147. *
  148. * A.7.a IF (need to right-adjust the byte) THEN
  149. */
  150. if ( mover > 0 )
  151. {
  152. /*
  153. * A.7.a.1 RETRIEVE 4 continuous byte from offset Index in block
  154. */
  155. {
  156. unsigned long l0, l1, l2, l3;
  157. l0 = (unsigned long)inchar[index*4] << 24;
  158. l1 = (unsigned long)(0x000000FF & inchar[index*4+1 ]) << 16;
  159. l2 = (unsigned long)(0x000000FF & inchar[index*4+2 ]) << 8;
  160. l3 = (unsigned long)(0x000000FF & inchar[index*4+3 ]);
  161. inlong = l0 + l1 + l2 + l3;
  162. }
  163. /*
  164. * A.7.a.2 RIGHT adjust this value
  165. */
  166. *iout = inlong >> mover;
  167. /*
  168. * A.7.a.3 MASK out the bits wanted only !result in *out
  169. */
  170. *iout = (*iout & mask);
  171. } /* If */
  172. /*
  173. * A.7.b ELSE IF (byte is split across a word break) THEN
  174. */
  175. else if ( mover < 0 )
  176. {
  177. /*
  178. * !
  179. * !Get the valid bits out of the FIRST WORD
  180. * !
  181. * A.7.b.1 CALCULATE #times to move retrieve data left so
  182. * the 1st significant bit aligns with MSB of word
  183. * A.7.b.2 CALCULATE #times to move data that's aligned
  184. * with MSB so that it aligns with LSB of word
  185. */
  186. movel = -mover;
  187. mover = WORD_BIT_CNT - movel; /* WORD_BIT_CNT is 32 */
  188. /*
  189. * A.7.b.3 RETRIEVE 4-byte word from offset Index from block
  190. */
  191. {
  192. unsigned long l0, l1, l2, l3;
  193. l0 = (unsigned long)(0x000000FF & inchar[index*4]) << 24;
  194. l1 = (unsigned long)(0x000000FF & inchar[index*4+1 ]) << 16;
  195. l2 = (unsigned long)(0x000000FF & inchar[index*4+2 ]) << 8;
  196. l3 = (unsigned long)(0x000000FF & inchar[index*4+3 ]);
  197. inlong = l0 + l1 + l2 + l3;
  198. }
  199. /*
  200. * A.7.b.4 SHIFT retrieve this data all the way left !Left portion
  201. */
  202. /*
  203. * !
  204. * !Now Get the valid bits out of the SECOND WORD
  205. * !
  206. * A.7.b.5 RETRIEVE the next 4-byte word from block
  207. */
  208. *iout = inlong << movel;
  209. {
  210. unsigned long l0, l1, l2, l3;
  211. l0 = (unsigned long)(0x000000FF & inchar[index*4+4]) << 24;
  212. l1 = (unsigned long)(0x000000FF & inchar[index*4+5 ]) << 16;
  213. l2 = (unsigned long)(0x000000FF & inchar[index*4+6 ]) << 8;
  214. l3 = (unsigned long)(0x000000FF & inchar[index*4+7 ]);
  215. inlong = l0 + l1 + l2 + l3;
  216. }
  217. /*
  218. * A.7.b.6 SHIFT this data all the way right !Right portion
  219. * A.7.b.7 OR the Left portion and Right portion together
  220. * A.7.b.8 MASK out the #bits wanted only !result in *iout
  221. */
  222. temp = inlong >> mover;
  223. *iout = *iout|temp;
  224. *iout &= mask;
  225. /*
  226. THE BYTE IS ALREADY RIGHT ADJUSTED.
  227. */
  228. }
  229. else
  230. /*
  231. * A.7.c ELSE !the byte is already adjusted, no shifts needed
  232. */
  233. {
  234. /*
  235. * A.7.c.1 RETRIEVE the next 4-byte word from block
  236. */
  237. {
  238. unsigned long l0, l1, l2, l3;
  239. l0 = (unsigned long)(0x000000FF & inchar[index*4]) << 24;
  240. l1 = (unsigned long)(0x000000FF & inchar[index*4+1 ]) << 16;
  241. l2 = (unsigned long)(0x000000FF & inchar[index*4+2 ]) << 8;
  242. l3 = (unsigned long)(0x000000FF & inchar[index*4+3 ]);
  243. inlong = l0 + l1 + l2 + l3;
  244. }
  245. /*
  246. * A.7.c.2 MASK out the bits wanted only !result in *out
  247. */
  248. *iout = inlong&mask;
  249. }
  250. /*
  251. * A.7.c ENDIF !the byte is already adjusted
  252. */
  253. /*
  254. *
  255. * A.8 DEBUG printing
  256. */
  257. DPRINT3 ("gbyte(skip=%d %d bits)= %lu stored as ", *iskip, nbits, *iout);
  258. /*
  259. *
  260. * A.9 BUMP pointer up
  261. */
  262. *iskip += nbits;
  263. /*
  264. * END OF FUNCTION
  265. *
  266. *
  267. */
  268. }
  269. /*
  270. *
  271. *****************************************************************
  272. * B. FUNCTION: gbyte_quiet
  273. * called to extract data of specified length from
  274. * specified offset from a block of type char;
  275. * Identical to gbyte() except it does not print out in debug mode;
  276. *
  277. * INTERFACE:
  278. * void gbyte_quiet (inchar, iout, iskip, nbits)
  279. *
  280. * ARGUMENTS (I=input, O=output, I&O=input and output):
  281. * (I) char *inchar
  282. * The fullword in memory from which unpacking is to
  283. * begin, successive fullwords will be fetched as required.
  284. * (O) unsigned long *iout
  285. * The value read from memory that's being returned.
  286. * (I&O) unsigned long *iskip
  287. * a fullword integer specifying the inital offset
  288. * in bits of the first byte, counted from the
  289. * leftmost bit in Inchar. Gets updated upon exit;
  290. * (I) unsigned long nbits
  291. * a fullword integer specifying the number of bits
  292. * in each byte to be unpacked. Legal byte widths
  293. * are in the range 1 - 32, bytes of width less than 32
  294. * will be right justified in the low-order positions
  295. * of the unpacked fullwords with high-order zero fill.
  296. *
  297. * RETURN CODE: none;
  298. *****************************************************************
  299. *
  300. */
  301. #if PROTOTYPE_NEEDED
  302. void gbyte_quiet (char *inchar, unsigned long *iout, unsigned long *iskip,
  303. unsigned long nbits)
  304. #else
  305. void gbyte_quiet (inchar, iout, iskip, nbits)
  306. char *inchar; /* input */
  307. unsigned long *iout; /* output, is the value returned */
  308. unsigned long *iskip; /* input, gets updated */
  309. unsigned long nbits; /* input */
  310. #endif
  311. {
  312. long masks[32];
  313. long icon,index,ii,mover,movel;
  314. unsigned long temp, mask, inlong;
  315. /*
  316. * B.1 INITIALIZE mask possibilities of all bits set from LSB to
  317. * a particular bit position; !bit position range: 0 to 31
  318. */
  319. masks[0] = 1;
  320. masks[1] = 3;
  321. masks[2] = 7;
  322. masks[3] = 15;
  323. masks[4] = 31;
  324. masks[5] = 63;
  325. masks[6] = 127;
  326. masks[7] = 255;
  327. masks[8] = 511;
  328. masks[9] = 1023;
  329. masks[10] = 2047;
  330. masks[11] = 4095;
  331. masks[12] = 8191;
  332. masks[13] = 16383;
  333. masks[14] = 32767;
  334. masks[15] = 65535;
  335. masks[16] = 131071;
  336. masks[17] = 262143;
  337. masks[18] = 524287;
  338. masks[19] = 1048575;
  339. masks[20] = 2097151;
  340. masks[21] = 4194303;
  341. masks[22] = 8388607;
  342. masks[23] = 16777215;
  343. masks[24] = 33554431;
  344. masks[25] = 67108863;
  345. masks[26] = 134217727;
  346. masks[27] = 268435455;
  347. masks[28] = 536870911;
  348. masks[29] = 1073741823;
  349. masks[30] = 2147483647;
  350. masks[31] = -1;
  351. /* NBYTE MUST BE LESS THAN OR EQUAL TO WORD_BIT_CNT
  352. *
  353. * B.2 IF (trying to retrieve more than numbits_perword) THEN !here, 32
  354. * RETURN
  355. * ENDIF
  356. */
  357. icon = WORD_BIT_CNT - nbits;
  358. if ( icon < 0 )
  359. {
  360. return;
  361. }
  362. /*
  363. *
  364. * B.3 SET up mask needed for specified #bits to retrieve
  365. */
  366. mask = masks[nbits-1];
  367. /*
  368. *
  369. * B.4 CALCULATE Index !Byte offset from 'inchar' where retrieval begins
  370. */
  371. index = *iskip / WORD_BIT_CNT;
  372. /*
  373. *
  374. * B.5 CALCULATE Bit position within byte Index where retrieval begins
  375. */
  376. ii = *iskip % WORD_BIT_CNT;
  377. /*
  378. *
  379. * B.6 CALCULATE #times to Right-shift the retrieved data so it
  380. * is right adjusted
  381. */
  382. mover = icon - ii;
  383. /*
  384. *
  385. * B.7.a IF (need to right-adjust the byte) THEN
  386. */
  387. if ( mover > 0 )
  388. {
  389. /*
  390. * B.7.a.1 RETRIEVE 4 continuous byte from offset Index in block
  391. */
  392. {
  393. unsigned long l0, l1, l2, l3;
  394. l0 = (unsigned long)inchar[index*4] << 24;
  395. l1 = (unsigned long)(0x000000FF & inchar[index*4+1 ]) << 16;
  396. l2 = (unsigned long)(0x000000FF & inchar[index*4+2 ]) << 8;
  397. l3 = (unsigned long)(0x000000FF & inchar[index*4+3 ]);
  398. inlong = l0 + l1 + l2 + l3;
  399. }
  400. /*
  401. * B.7.a.2 RIGHT adjust this value
  402. */
  403. *iout = inlong >> mover;
  404. /*
  405. * B.7.a.3 MASK out the bits wanted only !result in *out
  406. */
  407. *iout = (*iout & mask);
  408. } /* If */
  409. /*
  410. * B.7.b ELSE IF (byte is split across a word break) THEN
  411. */
  412. else if ( mover < 0 )
  413. {
  414. /*
  415. * !
  416. * !Get the valid bits out of the FIRST WORD
  417. * !
  418. * B.7.b.1 CALCULATE #times to move retrieve data left so
  419. * the 1st significant bit aligns with MSB of word
  420. * B.7.b.2 CALCULATE #times to move data that's aligned
  421. * with MSB so that it aligns with LSB of word
  422. */
  423. movel = -mover;
  424. mover = WORD_BIT_CNT - movel; /* WORD_BIT_CNT is 32 */
  425. /*
  426. * B.7.b.3 RETRIEVE 4-byte word from offset Index from block
  427. */
  428. {
  429. unsigned long l0, l1, l2, l3;
  430. l0 = (unsigned long)(0x000000FF & inchar[index*4]) << 24;
  431. l1 = (unsigned long)(0x000000FF & inchar[index*4+1 ]) << 16;
  432. l2 = (unsigned long)(0x000000FF & inchar[index*4+2 ]) << 8;
  433. l3 = (unsigned long)(0x000000FF & inchar[index*4+3 ]);
  434. inlong = l0 + l1 + l2 + l3;
  435. }
  436. /*
  437. * B.7.b.4 SHIFT retrieve this data all the way left !Left portion
  438. */
  439. /*
  440. * !
  441. * !Now Get the valid bits out of the SECOND WORD
  442. * !
  443. * B.7.b.5 RETRIEVE the next 4-byte word from block
  444. */
  445. *iout = inlong << movel;
  446. {
  447. unsigned long l0, l1, l2, l3;
  448. l0 = (unsigned long)(0x000000FF & inchar[index*4+4]) << 24;
  449. l1 = (unsigned long)(0x000000FF & inchar[index*4+5 ]) << 16;
  450. l2 = (unsigned long)(0x000000FF & inchar[index*4+6 ]) << 8;
  451. l3 = (unsigned long)(0x000000FF & inchar[index*4+7 ]);
  452. inlong = l0 + l1 + l2 + l3;
  453. }
  454. /*
  455. * B.7.b.6 SHIFT this data all the way right !Right portion
  456. * B.7.b.7 OR the Left portion and Right portion together
  457. * B.7.b.8 MASK out the #bits wanted only !result in *iout
  458. */
  459. temp = inlong >> mover;
  460. *iout = *iout|temp;
  461. *iout &= mask;
  462. /*
  463. THE BYTE IS ALREADY RIGHT ADJUSTED.
  464. */
  465. }
  466. else
  467. /*
  468. * B.7.c ELSE !the byte is already adjusted, no shifts needed
  469. */
  470. {
  471. /*
  472. * B.7.c.1 RETRIEVE the next 4-byte word from block
  473. */
  474. {
  475. unsigned long l0, l1, l2, l3;
  476. l0 = (unsigned long)(0x000000FF & inchar[index*4]) << 24;
  477. l1 = (unsigned long)(0x000000FF & inchar[index*4+1 ]) << 16;
  478. l2 = (unsigned long)(0x000000FF & inchar[index*4+2 ]) << 8;
  479. l3 = (unsigned long)(0x000000FF & inchar[index*4+3 ]);
  480. inlong = l0 + l1 + l2 + l3;
  481. }
  482. /*
  483. * B.7.c.2 MASK out the bits wanted only !result in *out
  484. */
  485. *iout = inlong&mask;
  486. }
  487. /*
  488. * B.7.c ENDIF !the byte is already adjusted
  489. */
  490. /*
  491. *
  492. * B.8 BUMP pointer up
  493. */
  494. *iskip += nbits;
  495. /*
  496. * END OF FUNCTION
  497. *
  498. */
  499. }