5
#include "raster3d_intern.h"
7
/*--------------------------------------------------------------------------*/
9
#define XDR_DOUBLE_LENGTH 8
10
#define XDR_DOUBLE_NOF_EXP_BYTES 2
11
#define XDR_FLOAT_LENGTH 4
12
#define XDR_FLOAT_NOF_EXP_BYTES 1
14
/*--------------------------------------------------------------------------*/
16
void Rast3d_fpcompress_print_binary(char *c, int numBits)
21
bit = 1 << (numBits - 1);
23
for (i = 0; i < numBits; i++) {
24
printf("%d", (*((unsigned char *)c) & bit) != 0);
29
/*--------------------------------------------------------------------------*/
31
void Rast3d_fpcompress_dissect_xdr_double(unsigned char *numPointer)
35
sign = *numPointer >> 7;
36
exponent = (*numPointer << 1) | (*(numPointer + 1) >> 7);
38
printf("%f: sign = ", *((float *)numPointer));
39
Rast3d_fpcompress_print_binary(&sign, 1);
41
Rast3d_fpcompress_print_binary(&exponent, 8);
42
printf(" mantissa = ");
43
Rast3d_fpcompress_print_binary((char *)(numPointer + 1), 7);
44
Rast3d_fpcompress_print_binary((char *)(numPointer + 2), 8);
45
Rast3d_fpcompress_print_binary((char *)(numPointer + 3), 8);
49
/*--------------------------------------------------------------------------*/
51
static unsigned char clearMask[9] =
52
{ 255, 128, 192, 224, 240, 248, 252, 254, 255 };
54
/*--------------------------------------------------------------------------*/
56
#define ALL_NULL_CODE 2
57
#define ZERO_NULL_CODE 1
58
#define SOME_NULL_CODE 0
60
/*--------------------------------------------------------------------------*/
63
G_fpcompress_rearrangeEncodeFloats(unsigned char *src, int size,
64
int precision, unsigned char *dst,
65
int *length, int *offsetMantissa)
67
unsigned int nNullBits, nBits;
68
register unsigned char *srcStop;
69
register unsigned char *cp0, *cp1, *cp2, *cp3, *nullBits;
70
unsigned char mask, isNull;
71
int gt8, gt16, srcIncrement, nofNull;
74
srcStop = src + size * XDR_FLOAT_LENGTH;
76
if ((precision >= 23) || (precision == -1)) {
81
while (srcStop != src) {
82
*cp3++ = *src++; /* sign + 7 exponent bits */
83
*cp2++ = *src++; /* 1 exponent bit + 7 ms mantissa bits */
84
*cp1++ = *src++; /* 8 mantissa bits */
85
*cp0++ = *src++; /* 8 ls mantissa bits */
88
*length = size * XDR_FLOAT_LENGTH;
89
*offsetMantissa = size;
96
while (srcStop != (unsigned char *)f)
97
nofNull += Rast3d_is_xdr_null_float(f++);
99
if (nofNull == size) {
100
*dst = (unsigned char)ALL_NULL_CODE;
108
precision += 1; /* treat the ls exponent bit like an addl mantissa bit */
110
*dst = (unsigned char)(nofNull == 0 ? ZERO_NULL_CODE : SOME_NULL_CODE);
112
gt16 = precision > 16;
114
srcIncrement = 1 + (!gt8) + (!gt16);
120
cp0 = nullBits + size / 8 + ((size % 8) != 0);
123
cp3 = cp0 + size - nofNull;
124
cp2 = cp3 + size - nofNull;
125
cp1 = cp3 + (gt8 + gt16) * (size - nofNull);
127
mask = clearMask[precision];
128
nBits = nNullBits = 0;
130
while (srcStop != src) {
132
isNull = Rast3d_is_xdr_null_float((float *)src);
135
*nullBits |= ((unsigned char)isNull << nNullBits++);
136
if (nNullBits == 8) {
142
*nullBits = (unsigned char)isNull;
147
src += XDR_FLOAT_LENGTH;
152
/* printf ("write src cp0 %d %d (%d %d) %d\n", *src, *cp0, src, cp0, nullBits); */
160
if (nBits && precision) {
161
*cp1 |= (unsigned char)((unsigned char)(*src & mask) >> nBits);
163
/*printf ("%d\n", ((*src & mask) >> nBits) << nBits); */
165
if (8 - nBits < precision) {
168
/*printf ("%d %d\n", *cp1, (*src & mask) << (8 - nBits)); */
171
(unsigned char)((unsigned char)((*src & mask)) <<
173
nBits += precision - 8;
176
nBits = (nBits + precision) % 8;
182
*cp1 = (unsigned char)(*src & mask);
183
/* printf ("%d %d %d\n", *cp1, *src, nBits); */
184
nBits = (nBits + precision) % 8;
192
*length = 1; /* null-bit-vector indicator-byte */
194
if (nofNull) /* length of null-bit-vector */
195
*length += size / 8 + ((size % 8) != 0);
198
*length += (gt8 + gt16 + (precision == 0) + 1) * (size - nofNull) +
199
((precision * (size - nofNull)) / 8) +
200
(((precision * (size - nofNull)) % 8) != 0);
202
*offsetMantissa = size - nofNull;
205
/*--------------------------------------------------------------------------*/
208
G_fpcompress_rearrangeEncodeDoubles(unsigned char *src, int size,
209
int precision, unsigned char *dst,
210
int *length, int *offsetMantissa)
212
unsigned int nNullBits, nBits;
213
unsigned char isNull;
214
register unsigned char *srcStop;
215
register unsigned char *cp0, *cp1, *cp2, *cp3;
216
register unsigned char *cp4, *cp5, *cp6, *cp7, *nullBits;
218
int gt8, gt16, gt24, gt32, gt40, gt48, srcIncrement, nofNull;
221
srcStop = src + size * XDR_DOUBLE_LENGTH;
223
if ((precision >= 52) || (precision == -1)) {
233
while (srcStop != src) {
234
*cp7++ = *src++; /* sign + 7 ms exponent bits */
235
*cp6++ = *src++; /* 4 exponent bits + 4 ms mantissa bits */
236
*cp5++ = *src++; /* 8 mantissa bits */
241
*cp0++ = *src++; /* 8 ls mantissa bits */
244
*length = size * XDR_DOUBLE_LENGTH;
245
*offsetMantissa = size;
250
precision += 4; /* treat the 4 ls exponent bits like addl mantissa bits */
254
while (srcStop != (unsigned char *)d)
255
nofNull += Rast3d_is_xdr_null_double(d++);
257
if (nofNull == size) {
258
*dst = (unsigned char)ALL_NULL_CODE;
266
*dst = (unsigned char)(nofNull == 0 ? ZERO_NULL_CODE : SOME_NULL_CODE);
268
gt48 = precision > 48;
269
gt40 = precision > 40;
270
gt32 = precision > 32;
271
gt24 = precision > 24;
272
gt16 = precision > 16;
275
1 + (!gt8) + (!gt16) + (!gt24) + (!gt32) + (!gt40) + (!gt48);
281
cp0 = nullBits + size / 8 + ((size % 8) != 0);
284
cp7 = cp0 + size - nofNull;
285
cp6 = cp7 + size - nofNull;
286
cp5 = cp6 + size - nofNull;
287
cp4 = cp5 + size - nofNull;
288
cp3 = cp4 + size - nofNull;
289
cp2 = cp3 + size - nofNull;
290
cp1 = cp7 + (gt8 + gt16 + gt24 + gt32 + gt40 + gt48) * (size - nofNull);
292
mask = clearMask[precision];
293
nBits = nNullBits = 0;
295
while (srcStop != src) {
297
isNull = Rast3d_is_xdr_null_double((double *)src);
300
*nullBits |= ((unsigned char)isNull << nNullBits++);
301
if (nNullBits == 8) {
307
*nullBits = (unsigned char)isNull;
312
src += XDR_DOUBLE_LENGTH;
339
if (nBits && precision) {
340
*cp1 |= (unsigned char)((unsigned char)(*src & mask) >> nBits);
341
if (8 - nBits < precision) {
344
(unsigned char)(((unsigned char)(*src & mask)) <<
346
nBits += precision - 8;
349
nBits = (nBits + precision) % 8;
355
*cp1 = (unsigned char)(*src & mask);
356
nBits = (nBits + precision) % 8;
367
*length += size / 8 + ((size % 8) != 0);
370
(1 + gt8 + gt16 + gt24 + gt32 + gt40 + gt48 +
372
0)) * (size - nofNull) + ((precision * (size - nofNull)) / 8) +
373
(((precision * (size - nofNull)) % 8) != 0);
376
*offsetMantissa = 2 * (size - nofNull);
378
*offsetMantissa = *length;
381
/*--------------------------------------------------------------------------*/
384
G_fpcompress_rearrangeDecodeFloats(unsigned char *src, int size,
385
int precision, unsigned char *dst)
387
unsigned int nNullBits, nBits;
388
register unsigned char *dstStop;
389
register unsigned char *cp0, *cp1, *cp2, *cp3, *nullBits;
390
unsigned char mask, isNull;
391
int gt8, gt16, dstIncrement, nofNull;
394
if ((precision != -1) && (precision <= 15)) { /* 23 - 8 */
396
dstStop = dst + XDR_FLOAT_LENGTH * size + 3;
397
while (dstStop != cp3) {
399
cp3 += XDR_FLOAT_LENGTH;
402
if (precision <= 7) {
404
dstStop = dst + XDR_FLOAT_LENGTH * size + 2;
405
while (dstStop != cp3) {
407
cp3 += XDR_FLOAT_LENGTH;
412
dstStop = dst + size * XDR_FLOAT_LENGTH;
414
if ((precision >= 23) || (precision == -1)) {
419
while (dstStop != dst) {
429
if (*src == (unsigned char)ALL_NULL_CODE) {
431
while (dstStop != (unsigned char *)f)
432
Rast3d_set_xdr_null_float(f++);
437
precision += 1; /* treat the ls exponent bit like an addl mantissa bit */
439
gt16 = precision > 16;
441
dstIncrement = 1 + (!gt8) + (!gt16);
448
if (*src == (unsigned char)SOME_NULL_CODE) {
450
fStop = (float *)(src + size * XDR_FLOAT_LENGTH);
451
while (fStop != f++) {
452
nofNull += ((*nullBits & ((unsigned char)1 << nNullBits++)) != 0);
453
if (nNullBits == 8) {
462
cp0 = nullBits + size / 8 + ((size % 8) != 0);
465
cp3 = cp0 + size - nofNull;
466
cp2 = cp3 + size - nofNull;
467
cp1 = cp3 + (gt8 + gt16) * (size - nofNull);
469
mask = clearMask[precision];
470
nBits = nNullBits = 0;
472
while (dstStop != dst) {
474
isNull = *nullBits & ((unsigned char)1 << nNullBits++);
476
if (nNullBits == 8) {
482
Rast3d_set_xdr_null_float((float *)dst);
483
dst += XDR_FLOAT_LENGTH;
494
if (nBits && precision) {
495
*dst = (unsigned char)((*cp1 << nBits) & mask);
497
if (8 - nBits < precision) {
499
*dst |= (unsigned char)((*cp1 >> (8 - nBits)) & mask);
500
nBits += precision - 8;
503
nBits = (nBits + precision) % 8;
509
*dst = (unsigned char)(*cp1 & mask);
510
nBits = (nBits + precision) % 8;
519
/*--------------------------------------------------------------------------*/
522
G_fpcompress_rearrangeDecodeDoubles(unsigned char *src, int size,
523
int precision, unsigned char *dst)
525
unsigned int nNullBits, nBits;
526
register unsigned char *dstStop;
527
register unsigned char *cp0, *cp1, *cp2, *cp3;
528
register unsigned char *cp4, *cp5, *cp6, *cp7, *nullBits;
529
unsigned char mask, isNull;
530
int gt8, gt16, gt24, gt32, gt40, gt48, dstIncrement, offs, nofNull;
533
if ((precision != -1) && (precision <= 44)) {
534
for (offs = 7; offs >= (precision + 19) / 8; offs--) {
536
dstStop = dst + XDR_DOUBLE_LENGTH * size + offs;
537
while (dstStop != cp7) {
539
cp7 += XDR_DOUBLE_LENGTH;
544
dstStop = dst + size * XDR_DOUBLE_LENGTH;
546
if ((precision >= 52) || (precision == -1)) {
556
while (dstStop != dst) {
570
if (*src == (unsigned char)ALL_NULL_CODE) {
571
/*printf ("all null\n"); */
573
while (dstStop != (unsigned char *)d)
574
Rast3d_set_xdr_null_double(d++);
579
precision += 4; /* treat the 4 ls exponent bits like addl mantissa bits */
581
gt48 = precision > 48;
582
gt40 = precision > 40;
583
gt32 = precision > 32;
584
gt24 = precision > 24;
585
gt16 = precision > 16;
589
1 + (!gt8) + (!gt16) + (!gt24) + (!gt32) + (!gt40) + (!gt48);
596
if (*src == (unsigned char)SOME_NULL_CODE) {
598
dStop = (double *)(src + size * XDR_DOUBLE_LENGTH);
599
while (dStop != d++) {
600
nofNull += ((*nullBits & ((unsigned char)1 << nNullBits++)) != 0);
601
if (nNullBits == 8) {
610
cp0 = nullBits + size / 8 + ((size % 8) != 0);
613
cp7 = cp0 + size - nofNull;
614
cp6 = cp7 + size - nofNull;
615
cp5 = cp6 + size - nofNull;
616
cp4 = cp5 + size - nofNull;
617
cp3 = cp4 + size - nofNull;
618
cp2 = cp3 + size - nofNull;
619
cp1 = cp7 + (gt8 + gt16 + gt24 + gt32 + gt40 + gt48) * (size - nofNull);
621
mask = clearMask[precision];
622
nBits = nNullBits = 0;
624
while (dstStop != dst) {
626
isNull = *nullBits & ((unsigned char)1 << nNullBits++);
628
if (nNullBits == 8) {
634
Rast3d_set_xdr_null_double((double *)dst);
635
dst += XDR_DOUBLE_LENGTH;
662
if (nBits && precision) {
663
*dst = (unsigned char)((*cp1 << nBits) & mask);
665
if (8 - nBits < precision) {
667
*dst |= (unsigned char)((*cp1 >> (8 - nBits)) & mask);
668
nBits += precision - 8;
671
nBits = (nBits + precision) % 8;
677
*dst = (unsigned char)(*cp1 & mask);
678
nBits = (nBits + precision) % 8;
687
/*--------------------------------------------------------------------------*/
690
Rast3d_fpcompress_write_xdr_nums(int fd, char *src, int nofNum, int precision,
691
char *compressBuf, int isFloat)
698
G_fpcompress_rearrangeEncodeFloats((unsigned char *)src, nofNum, precision,
699
(unsigned char *)(compressBuf + 1),
700
&nBytes, &offsetMantissa);
702
G_fpcompress_rearrangeEncodeDoubles((unsigned char *)src, nofNum, precision,
703
(unsigned char *)(compressBuf + 1),
704
&nBytes, &offsetMantissa);
707
status = G_zlib_write(fd, (unsigned char *)compressBuf, nBytes + 1);
710
Rast3d_error("Rast3d_fpcompress_write_xdr_nums: write error");
717
/*--------------------------------------------------------------------------*/
720
Rast3d_fpcompress_read_xdr_nums(int fd, char *dst, int nofNum, int fileBytes,
721
int precision, char *compressBuf, int isFloat)
724
int lengthEncode, lengthDecode;
726
char *src, *dest, *srcStop;
727
nBytes = (isFloat ? XDR_FLOAT_LENGTH : XDR_DOUBLE_LENGTH);
729
status = G_zlib_read(fd, fileBytes, (unsigned char *)compressBuf,
730
nofNum * nBytes + 1);
733
Rast3d_error("Rast3d_fpcompress_read_xdr_nums: read error");
737
/* This code is kept for backward compatibility */
738
if (*compressBuf++ == 1) {
740
Rast3d_rle_decode(compressBuf, dst, nofNum * nBytes, 1,
741
&lengthEncode, &lengthDecode);
742
if (*dst == ALL_NULL_CODE)
743
Rast3d_fatal_error("Rast3d_fpcompress_read_xdr_nums: wrong code");
745
if (status == nofNum * nBytes)
746
status -= lengthDecode - lengthEncode;
748
src = compressBuf + status - 1;
749
srcStop = compressBuf + lengthEncode - 1;
750
dest = compressBuf + (status - lengthEncode) + lengthDecode - 1;
751
while (src != srcStop)
755
srcStop = src + lengthDecode;
757
while (src != srcStop)
762
G_fpcompress_rearrangeDecodeFloats((unsigned char *)compressBuf, nofNum, precision,
763
(unsigned char *)dst);
765
G_fpcompress_rearrangeDecodeDoubles((unsigned char *)compressBuf, nofNum, precision,
766
(unsigned char *)dst);