~ubuntu-branches/ubuntu/vivid/openbabel/vivid-proposed

« back to all changes in this revision

Viewing changes to src/binary_io.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Banck
  • Date: 2002-02-01 01:19:44 UTC
  • Revision ID: james.westby@ubuntu.com-20020201011944-4a9guzcsnpezzawx
Tags: upstream-1.99
ImportĀ upstreamĀ versionĀ 1.99

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//THIS
 
2
#include "binary_io.h"
 
3
 
 
4
namespace OpenBabel {
 
5
 
 
6
//test byte ordering
 
7
static int SSINT = 0x00000001;
 
8
static unsigned char *SSTPTR = (unsigned char*)&SSINT;
 
9
bool SSwabInt = (SSTPTR[0]!=0);
 
10
static const int TMPSIZE = sizeof(double);
 
11
 
 
12
/******************** reading generic binary data *************************/
 
13
unsigned int OB_io_read_binary(char* ccc, char *x, unsigned int size, unsigned int count)
 
14
{
 
15
    if (x == NULL || size == 0)
 
16
        return 0;
 
17
 
 
18
    if (size == 1)
 
19
    {
 
20
        memcpy(x, ccc, count);
 
21
        return count;
 
22
    }
 
23
    else
 
24
    {
 
25
        unsigned int sz = size * count;
 
26
        if (!SSwabInt)
 
27
                memcpy(x, ccc, sz);
 
28
        else
 
29
        {
 
30
                unsigned int i,j,k;
 
31
                unsigned char c, tmp[TMPSIZE];
 
32
 
 
33
                for ( i = 0 ; i < sz ; i += size )
 
34
                {
 
35
                        memcpy(tmp, &ccc[i], size);
 
36
                        for (j = 0, k = size - 1 ; j < k ; j++, k--) {
 
37
                                c = tmp[j]; tmp[j] = tmp[k]; tmp[k] = c;
 
38
                        }
 
39
                        memcpy(&x[i], tmp, size);
 
40
                }
 
41
        }
 
42
        return sz;
 
43
    }
 
44
}
 
45
unsigned int OB_io_read_binary(istream& ifs, char *x, unsigned int size, unsigned int count)
 
46
{
 
47
    if (x == NULL || size == 0)
 
48
        return 0;
 
49
 
 
50
    if (size == 1)
 
51
    {
 
52
        ifs.read(x, count);
 
53
        return count;
 
54
    }
 
55
    else
 
56
    {
 
57
        unsigned int sz = size * count;
 
58
        if (!SSwabInt)
 
59
                ifs.read(x, sz);
 
60
        else
 
61
        {
 
62
                unsigned int i,j,k;
 
63
                unsigned char c, tmp[TMPSIZE];
 
64
 
 
65
                for ( i = 0 ; i < count ; i++ )
 
66
                {
 
67
                        ifs.read((char*)&tmp[0], size);
 
68
                        for (j = 0, k = size - 1 ; j < k ; j++, k--) {
 
69
                                c = tmp[j]; tmp[j] = tmp[k]; tmp[k] = c;
 
70
                        }
 
71
                        memcpy(&x[i*size], tmp, size);
 
72
                }
 
73
        }
 
74
        return sz;
 
75
    }
 
76
}
 
77
 
 
78
/******************** writing generic binary data *************************/
 
79
unsigned int OB_io_write_binary(char *ccc, const char *x, unsigned int size, unsigned int count)
 
80
{
 
81
    if (x == NULL || size == 0)
 
82
        return 0;
 
83
 
 
84
    if (size == 1)
 
85
    {
 
86
        memcpy(ccc, x, count);
 
87
        return count;
 
88
    }
 
89
    else
 
90
    {
 
91
        unsigned int sz = size * count;
 
92
        if (!SSwabInt)
 
93
                memcpy(ccc, x, sz);
 
94
        else
 
95
        {
 
96
                unsigned i,j,k;
 
97
                unsigned char c, tmp[TMPSIZE];
 
98
 
 
99
                for (i = 0 ; i < sz ; i += size)
 
100
                {
 
101
                        memcpy(tmp, &x[i], size);
 
102
                        for (j = 0, k = size - 1 ; j < k ; j++, k-- ) {
 
103
                                c = tmp[j]; tmp[j] = tmp[k]; tmp[k] = c;
 
104
                        }
 
105
                        memcpy(&ccc[i], tmp, size);
 
106
                }
 
107
        }
 
108
        return sz;
 
109
    }
 
110
}
 
111
unsigned int OB_io_write_binary(ostream &ofs, const char *x, unsigned int size, unsigned int count)
 
112
{
 
113
    if (x == NULL || size == 0)
 
114
        return 0;
 
115
 
 
116
    if (size == 1)
 
117
    {
 
118
        ofs.write(x, count);
 
119
        return count;
 
120
    }
 
121
    else
 
122
    {
 
123
        unsigned int sz = size * count;
 
124
        if (!SSwabInt)
 
125
                ofs.write(x, sz);
 
126
        else
 
127
        {
 
128
                unsigned i,j,k;
 
129
                unsigned char c, tmp[TMPSIZE];
 
130
 
 
131
                for (i = 0 ; i < sz ; i += size)
 
132
                {
 
133
                        memcpy(tmp, &x[i], size);
 
134
                        for (j = 0, k = size - 1 ; j < k ; j++, k-- ) {
 
135
                                c = tmp[j]; tmp[j] = tmp[k]; tmp[k] = c;
 
136
                        }
 
137
                        ofs.write((char*)&tmp[0], size);
 
138
                }
 
139
        }
 
140
        return sz;
 
141
    }
 
142
}
 
143
 
 
144
/**********************reading STL strings****************************/
 
145
 
 
146
unsigned int OB_io_read_binary(char* ccc, string& str)
 
147
{
 
148
    char *buffer;
 
149
    unsigned int i = 0, idx = 0;
 
150
 
 
151
    idx    += OB_io_read_binary(ccc, (char*) &i, sizeof(unsigned int), 1);
 
152
    buffer  = new char[i+1];
 
153
    idx    += OB_io_read_binary(&ccc[idx], buffer, sizeof(char), i);
 
154
 
 
155
    buffer[i] = '\0';
 
156
    str       = buffer;
 
157
 
 
158
        delete [] buffer;
 
159
 
 
160
    return idx;
 
161
}
 
162
unsigned int OB_io_read_binary(istream& ifs, string& str)
 
163
{
 
164
    char *buffer;
 
165
    unsigned int i = 0, idx = 0;
 
166
 
 
167
    idx    += OB_io_read_binary(ifs, (char*) &i, sizeof(unsigned int), 1);
 
168
    buffer  = new char[i+1];
 
169
    idx    += OB_io_read_binary(ifs, buffer, sizeof(char), i);
 
170
 
 
171
    buffer[i] = '\0';
 
172
    str       = buffer;
 
173
 
 
174
        delete [] buffer;
 
175
 
 
176
    return idx;
 
177
}
 
178
 
 
179
/******************** writing STL strings *************************/
 
180
 
 
181
unsigned int OB_io_write_binary(char* ccc, const string& str)
 
182
{
 
183
    unsigned int idx = 0, size = str.size();
 
184
 
 
185
    idx += OB_io_write_binary(ccc, (char*) &size, sizeof(unsigned int), 1);
 
186
    idx += OB_io_write_binary(&ccc[idx], str.c_str(), sizeof(char), size);
 
187
 
 
188
    return idx;
 
189
}
 
190
unsigned int OB_io_write_binary(ostream& ofs, const string& str)
 
191
{
 
192
    unsigned int idx = 0, size = str.size();
 
193
 
 
194
    idx += OB_io_write_binary(ofs, (char*) &size, sizeof(unsigned int), 1);
 
195
    idx += OB_io_write_binary(ofs, str.c_str(), sizeof(char), size);
 
196
 
 
197
    return idx;
 
198
}
 
199
 
 
200
/******************* writing compressed data *************************/
 
201
/*!
 
202
**\fn OB_io_write_binary_compressed(char*ccc, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
 
203
**\brief Writes an unsigned interger array out in a platform independed
 
204
**compressed binary format.
 
205
**\param ccc A character array that the binary is written to
 
206
**\param x An unsigned integer array to be written to ccc.
 
207
**\param NumBits The number of bits that will be used to store
 
208
**each unsigned integer.  The largest value in x must be less than
 
209
**2^NumBits.
 
210
**\param NumInts The number of integers in x
 
211
**\return The number of bytes written to ccc.  This value should
 
212
**always be 1+(NumBits*NumInts)/8 (integer division).
 
213
*/
 
214
unsigned int OB_io_write_binary_compressed(char*ccc, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
 
215
  {
 
216
    //If there are no values or x is NULL do nothing
 
217
    if (!NumInts || x==NULL) return 0;
 
218
 
 
219
    //If 32 or more bits are specified simply write uncompressed
 
220
    if (NumBits >=32) return OB_io_write_binary(ccc,(const char*) x, sizeof(unsigned int), NumInts);
 
221
 
 
222
    bool swap = !SSwabInt; 
 
223
    unsigned int bitarraysize = 1+(NumBits*NumInts)/8;
 
224
    unsigned char *cc = (unsigned char*) ccc;
 
225
    unsigned int i,j;
 
226
    for (i=0 ; i<bitarraysize ; i++) cc[i] = 0;
 
227
    unsigned char mask1[8],mask2[8];
 
228
    mask2[7] = 127;
 
229
    mask2[6] = 63;
 
230
    mask2[5] = 31;
 
231
    mask2[4] = 15;
 
232
    mask2[3] = 7;
 
233
    mask2[2] = 3;
 
234
    mask2[1] = 1;
 
235
    mask2[0] = 0;
 
236
    for (i=0 ; i<8 ; i++) mask1[i] = ~mask2[i];
 
237
    unsigned int bitshift=0;
 
238
    unsigned int bytes=0;
 
239
    unsigned int value;
 
240
    unsigned char *cptr = (unsigned char*)&value;
 
241
    for (i=0 ; i<NumInts ; i++) {
 
242
        if (swap) {
 
243
            cptr[0] = ((unsigned char*)(&x[i]))[3]; 
 
244
            cptr[1] = ((unsigned char*)(&x[i]))[2]; 
 
245
            cptr[2] = ((unsigned char*)(&x[i]))[1]; 
 
246
            cptr[3] = ((unsigned char*)(&x[i]))[0]; 
 
247
          }
 
248
        else      {value = x[i];}
 
249
        for (j=0 ; j<NumBits/8 ; j++) {
 
250
            cc[bytes+0+j] |= (cptr[j]<<(bitshift  ))&mask1[bitshift];
 
251
            cc[bytes+1+j] |= (cptr[j]>>(8-bitshift))&mask2[bitshift];
 
252
          }
 
253
        cc[bytes+0+j] |= (cptr[j]<<(bitshift  ))&mask1[bitshift];
 
254
        if ((bitshift + NumBits%8) > 7) cc[bytes+1+j] |= (cptr[j]>>(8-bitshift))&mask2[bitshift];
 
255
        bitshift += NumBits;
 
256
        while (bitshift > 7) {bitshift-=8; bytes++;}
 
257
      }
 
258
    return bitarraysize;
 
259
  }
 
260
/*!
 
261
**\fn OB_io_write_binary_compressed(ostream& ostr, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
 
262
**\brief Writes an unsigned interger array out in a platform independed
 
263
**compressed binary format.
 
264
**\param ostr An output stream that the binary is written to
 
265
**\param x An unsigned integer array to be written to ostr.
 
266
**\param NumBits The number of bits that will be used to store
 
267
**each unsigned integer.  The largest value in x must be less than
 
268
**2^NumBits.
 
269
**\param NumInts The number of integers in x
 
270
**\return The number of bytes written to ostr.  This value should
 
271
**always be 1+(NumBits*NumInts)/8 (integer division).
 
272
*/
 
273
unsigned int OB_io_write_binary_compressed(ostream& ostr, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
 
274
  {
 
275
    //If there are no values or x is NULL do nothing
 
276
    if (!NumInts || x==NULL) return 0;
 
277
 
 
278
    //If 32 or more bits are specified simply write uncompressed
 
279
    if (NumBits >=32) return OB_io_write_binary(ostr,(const char*) x, sizeof(unsigned int), NumInts);
 
280
 
 
281
    unsigned int bitarraysize = 1+(NumBits*NumInts)/8;
 
282
    char *cc = new char [bitarraysize];
 
283
    unsigned int idx = OB_io_write_binary_compressed(cc,x,NumBits,NumInts);
 
284
    ostr.write(cc,bitarraysize);
 
285
    delete [] cc;
 
286
    return idx;
 
287
  }
 
288
 
 
289
/*!
 
290
**\fn OB_io_write_binary_compressed(char*ccc, float *x, unsigned int NumBits, unsigned int Nfloats)
 
291
**\brief Writes a float array out in a platform independed
 
292
**compressed binary format.
 
293
**\param ccc A character array that the binary is written to
 
294
**\param x A float array to be written to ccc.
 
295
**\param NumBits The number of bits that will be used to store
 
296
**each unsigned integer.  The lost of resolution of the float
 
297
**values depends directly on how many bits are used.
 
298
**\param Nfloats The number of floats in x.
 
299
**\return The number of bytes written to ccc.  This value should
 
300
**always be 9+(NumBits*NumInts)/8 (integer division).
 
301
**\par Compression Info
 
302
**There is a loss of resolution of the floats using this routine.
 
303
**The greater the value of NumBits and the smaller the range of values
 
304
**in x, the smaller the loss of resolution.  The function 
 
305
**OB_io_util_calc_NumBits(float *x, unsigned int N, float res)
 
306
**will calculate how many bits are required for a given resolution and
 
307
**set of floats.
 
308
*/
 
309
unsigned int OB_io_write_binary_compressed(char*ccc, float *x, unsigned int NumBits, unsigned int Nfloats)
 
310
  {
 
311
    unsigned int idx=0;
 
312
 
 
313
    //If there are no values of x is NULL do nothing
 
314
    if (!Nfloats || x==NULL) return 0;
 
315
 
 
316
    //If 32 or more bits are specified simply write uncompressed
 
317
    if (NumBits >=32) return OB_io_write_binary(&ccc[idx],(const char*) x, sizeof(unsigned int), Nfloats);
 
318
 
 
319
 
 
320
 
 
321
    //Write max and min
 
322
    unsigned int i;
 
323
    float max = x[0];
 
324
    float min = x[0];
 
325
    for (i=0 ; i<Nfloats ; i++) {
 
326
        if (x[i] > max) max = x[i];
 
327
        if (x[i] < min) min = x[i];
 
328
      }
 
329
    idx += OB_io_write_binary(&ccc[idx],(const char*)&max,sizeof(float),1);
 
330
    idx += OB_io_write_binary(&ccc[idx],(const char*)&min,sizeof(float),1);
 
331
 
 
332
    //Integerize values and write out 
 
333
    unsigned int maxint = (unsigned int) 0; 
 
334
    for (i=0 ; i<NumBits ; i++) maxint |= ((unsigned int)1)<<i;
 
335
    unsigned int *ix = new unsigned int [Nfloats]; 
 
336
    if (max!=min) {
 
337
        for (i=0 ; i<Nfloats ; i++) 
 
338
            ix[i] = (unsigned int) (((float)maxint*((x[i]-min)/(max-min))) + 0.499999999f);
 
339
      }
 
340
    else for (i=0 ; i<Nfloats ; i++) ix[i] = (unsigned int) 0;
 
341
    idx += OB_io_write_binary_compressed(&ccc[idx],ix,NumBits,Nfloats);
 
342
    delete [] ix;  
 
343
 
 
344
    return idx;
 
345
  }
 
346
/*!
 
347
**\fn OB_io_write_binary_compressed(ostream& ostr, float *x, unsigned int NumBits, unsigned int Nfloats)
 
348
**\brief Writes a float array out in a platform independed
 
349
**compressed binary format.
 
350
**\param ostr A character array that the binary is written to
 
351
**\param x A float array to be written to ostr.
 
352
**\param NumBits The number of bits that will be used to store
 
353
**each unsigned integer.  The lost of resolution of the float
 
354
**values depends directly on how many bits are used.
 
355
**\param Nfloats The number of floats in x.
 
356
**\return The number of bytes written to ccc.  This value should
 
357
**always be 9+(NumBits*NumInts)/8 (integer division).
 
358
**\par Compression Info
 
359
**There is a loss of resolution of the floats using this routine.
 
360
**The greater the value of NumBits and the smaller the range of values
 
361
**in x, the smaller the loss of resolution.  The function
 
362
**OB_io_util_calc_NumBits(float *x, unsigned int N, float res)
 
363
**will calculate how many bits are required for a given resolution and
 
364
**set of floats.
 
365
*/
 
366
unsigned int OB_io_write_binary_compressed(ostream& ostr, float *x, unsigned int NumBits, unsigned int Nfloats)
 
367
  {
 
368
    unsigned int idx=0;
 
369
 
 
370
    //If there are no values of x is NULL do nothing
 
371
    if (!Nfloats || x==NULL) return 0;
 
372
 
 
373
    //If 32 or more bits are specified simply write uncompressed
 
374
    if (NumBits >=32) return OB_io_write_binary(ostr,(const char*) x, sizeof(unsigned int), Nfloats);
 
375
 
 
376
    //Write max and min
 
377
    unsigned int i;
 
378
    float max = x[0];
 
379
    float min = x[0];
 
380
    for (i=0 ; i<Nfloats ; i++) {
 
381
        if (x[i] > max) max = x[i];
 
382
        if (x[i] < min) min = x[i];
 
383
      }
 
384
    idx += OB_io_write_binary(ostr,(const char*)&max,sizeof(float),1);
 
385
    idx += OB_io_write_binary(ostr,(const char*)&min,sizeof(float),1);
 
386
 
 
387
    //Integerize values and write out
 
388
    unsigned int maxint = (unsigned int) 0;
 
389
    for (i=0 ; i<NumBits ; i++) maxint |= ((unsigned int)1)<<i;
 
390
    unsigned int *ix = new unsigned int [Nfloats];
 
391
    if (max!=min) {
 
392
        for (i=0 ; i<Nfloats ; i++)
 
393
            ix[i] = (unsigned int) (((float)maxint*((x[i]-min)/(max-min))) + 0.499999999f);
 
394
      }
 
395
    else for (i=0 ; i<Nfloats ; i++) ix[i] = (unsigned int) 0;
 
396
    idx += OB_io_write_binary_compressed(ostr,ix,NumBits,Nfloats);
 
397
    delete [] ix;
 
398
 
 
399
 
 
400
    return idx;
 
401
  }
 
402
 
 
403
/******************* reading compressed data *************************/
 
404
/*!
 
405
**\fn OB_io_read_binary_compressed(char*ccc, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
 
406
**\brief Reads compressed binary data that was written with either
 
407
**OB_io_write_binary_compressed(char*ccc, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
 
408
**or
 
409
**OB_io_write_binary_compressed(ostream& ostr, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
 
410
**\param ccc A character array the binary is being read from
 
411
**\param x An array of unsigned ints the binary data will be extracted to
 
412
**\param NumBits The number of bits used to store each unsigned integer
 
413
**\param NumInts The number of integers stored in ccc
 
414
**\return The number of bytes read from ccc.  This value should
 
415
**always be 1+(NumBits*NumInts)/8 (integer division).
 
416
*/
 
417
unsigned int OB_io_read_binary_compressed(char*ccc, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
 
418
  {
 
419
    //If there are no values or x is NULL do nothing
 
420
    if (!NumInts || x==NULL) return 0;
 
421
 
 
422
    //If 32 or more bits are specified simply read uncompressed
 
423
    if (NumBits >=32) return OB_io_read_binary(ccc,(char*) x, sizeof(unsigned int), NumInts);
 
424
 
 
425
    //Read the values
 
426
    bool swap = !SSwabInt;
 
427
    unsigned int bitarraysize = 1+(NumBits*NumInts)/8;
 
428
    unsigned char *cc = (unsigned char*) ccc;
 
429
    unsigned int i,j;
 
430
    unsigned int mask = (unsigned int) 0;
 
431
    for (i=0 ; i<NumBits ; i++) mask |= ((unsigned int) 1) << i;
 
432
    unsigned char mask1[8],mask2[8];
 
433
    mask1[0] = 255;
 
434
    mask1[1] = 127;
 
435
    mask1[2] = 63;
 
436
    mask1[3] = 31;
 
437
    mask1[4] = 15;
 
438
    mask1[5] = 7;
 
439
    mask1[6] = 3;
 
440
    mask1[7] = 1;
 
441
    for (i=0 ; i<8 ; i++) mask2[i] = ~mask1[i];
 
442
    unsigned int bitshift=0;
 
443
    unsigned int bytes=0;
 
444
    unsigned int value;
 
445
    unsigned char *cptr = (unsigned char*)&value;
 
446
    for (i=0 ; i<NumInts ; i++) {
 
447
        value = (unsigned int) 0;
 
448
        for (j=0 ; j<NumBits/8 ; j++) {
 
449
            cptr[j]  = (cc[bytes+0+j]>>(  bitshift))&mask1[bitshift];
 
450
            cptr[j] |= (cc[bytes+1+j]<<(8-bitshift))&mask2[bitshift];
 
451
          }
 
452
        cptr[j]  = (cc[bytes+0+j]>>(  bitshift))&mask1[bitshift];
 
453
        if ((bitshift + NumBits%8) > 7) cptr[j] |= (cc[bytes+1+j]<<(8-bitshift))&mask2[bitshift];
 
454
 
 
455
        bitshift += NumBits;
 
456
        while (bitshift > 7) {bitshift-=8; bytes++;}
 
457
        if (swap) {
 
458
            ((unsigned char*)(&x[i]))[3] = cptr[0]; 
 
459
            ((unsigned char*)(&x[i]))[2] = cptr[1]; 
 
460
            ((unsigned char*)(&x[i]))[1] = cptr[2]; 
 
461
            ((unsigned char*)(&x[i]))[0] = cptr[3]; 
 
462
          }
 
463
        else x[i] = value;
 
464
        x[i] &= mask;
 
465
      }
 
466
 
 
467
    return bitarraysize;
 
468
  }
 
469
 
 
470
/*!
 
471
**\fn OB_io_read_binary_compressed(istream& istr, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
 
472
**\brief Reads compressed binary data that was written with either
 
473
**OB_io_write_binary_compressed(char*ccc, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
 
474
**or
 
475
**OB_io_write_binary_compressed(ostream& ostr, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
 
476
**\param istr An input file stream the binary is being read from
 
477
**\param x An array of unsigned ints the binary data will be extracted to
 
478
**\param NumBits The number of bits used to store each unsigned integer
 
479
**\param NumInts The number of integers stored in istr 
 
480
**\return The number of bytes read from istr.  This value should
 
481
**always be 1+(NumBits*NumInts)/8 (integer division).
 
482
*/
 
483
unsigned int OB_io_read_binary_compressed(istream& istr, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
 
484
  {
 
485
    //If there are no values or x is NULL do nothing
 
486
    if (!NumInts || x==NULL) return 0;
 
487
 
 
488
    //If 32 or more bits are specified simply read uncompressed
 
489
    if (NumBits >=32) return OB_io_read_binary(istr,(char*) x, sizeof(unsigned int), NumInts);
 
490
 
 
491
    unsigned int bitarraysize = 1+(NumBits*NumInts)/8;
 
492
    char *cc = new char [bitarraysize];
 
493
    istr.read(cc,bitarraysize);
 
494
    unsigned int idx = OB_io_read_binary_compressed(cc,x,NumBits,NumInts);
 
495
    delete [] cc;
 
496
    return idx;
 
497
  }
 
498
 
 
499
/*!
 
500
**\fn OB_io_read_binary_compressed(char*ccc, float *x, unsigned int NumBits, unsigned int Nfloats)
 
501
**\brief Reads compressed binary data that was written with either
 
502
**OB_io_write_binary_compressed(char*ccc, float *x, unsigned int NumBits, unsigned int NumInts)
 
503
**or
 
504
**OB_io_write_binary_compressed(ostream& ostr, float *x, unsigned int NumBits, unsigned int NumInts)
 
505
**\param ccc A character array the binary is being read from
 
506
**\param x An array of floats the binary data will be extracted to
 
507
**\param NumBits The number of bits used to store each float
 
508
**\param Nfloats The number of floats to be read 
 
509
**\return The number of bytes read from ccc.  This value should
 
510
**always be 1+(NumBits*NumInts)/8 (integer division).
 
511
*/
 
512
unsigned int OB_io_read_binary_compressed(char*ccc, float *x, unsigned int NumBits, unsigned int Nfloats)
 
513
  {
 
514
    unsigned int idx=0;
 
515
 
 
516
    //If there are no values or x is NULL do nothing
 
517
    if (!Nfloats || x==NULL) return 0;
 
518
 
 
519
    //If 32 or more bits are specified simply write uncompressed
 
520
    if (NumBits >=32) return OB_io_read_binary(&ccc[idx],(char*) x, sizeof(unsigned int), Nfloats);
 
521
 
 
522
    //Read max and min
 
523
    float max;
 
524
    float min;
 
525
    idx += OB_io_read_binary(&ccc[idx],(char*)&max,sizeof(float),1);
 
526
    idx += OB_io_read_binary(&ccc[idx],(char*)&min,sizeof(float),1);
 
527
 
 
528
    //Read in values
 
529
    unsigned int i;
 
530
    unsigned int maxint = (unsigned int) 0;
 
531
    for (i=0 ; i<NumBits ; i++) maxint |= ((unsigned int)1)<<i;
 
532
    unsigned int *ix = new unsigned int [Nfloats];
 
533
    idx += OB_io_read_binary_compressed(&ccc[idx],ix,NumBits,Nfloats);
 
534
    for (i=0 ; i<Nfloats ; i++) x[i] = (max-min)*((float)ix[i]/(float)maxint)+min;
 
535
    delete [] ix;
 
536
 
 
537
    return idx;
 
538
  }
 
539
 
 
540
/*!
 
541
**\fn OB_io_read_binary_compressed(istream& istr, float *x, unsigned int NumBits, unsigned int Nfloats)
 
542
**\brief Reads compressed binary data that was written with either
 
543
**OB_io_write_binary_compressed(char*ccc, float *x, unsigned int NumBits, unsigned int NumInts)
 
544
**or
 
545
**OB_io_write_binary_compressed(ostream& ostr, float *x, unsigned int NumBits, unsigned int NumInts)
 
546
**\param istr An input stream  the binary is being read from
 
547
**\param x An array of floats the binary data will be extracted to
 
548
**\param NumBits The number of bits used to store each float
 
549
**\param Nfloats The number of float values to be read
 
550
**\return The number of bytes read from istr.  This value should
 
551
**always be 1+(NumBits*NumInts)/8 (integer division).
 
552
*/
 
553
unsigned int OB_io_read_binary_compressed(istream& istr, float *x, unsigned int NumBits, unsigned int Nfloats)
 
554
  {
 
555
    unsigned int idx=0;
 
556
 
 
557
    //If there are no values or x is NULL do nothing
 
558
    if (!Nfloats || x==NULL) return 0;
 
559
 
 
560
    //If 32 or more bits are specified simply write uncompressed
 
561
    if (NumBits >=32) return OB_io_read_binary(istr,(char*) x, sizeof(unsigned int), Nfloats);
 
562
 
 
563
    //Read max and min
 
564
    float max;
 
565
    float min;
 
566
    idx += OB_io_read_binary(istr,(char*)&max,sizeof(float),1);
 
567
    idx += OB_io_read_binary(istr,(char*)&min,sizeof(float),1);
 
568
 
 
569
    //Read in values
 
570
    unsigned int i;
 
571
    unsigned int maxint = (unsigned int) 0;
 
572
    for (i=0 ; i<NumBits ; i++) maxint |= ((unsigned int)1)<<i;
 
573
    unsigned int *ix = new unsigned int [Nfloats];
 
574
    idx += OB_io_read_binary_compressed(istr,ix,NumBits,Nfloats);
 
575
    for (i=0 ; i<Nfloats ; i++) x[i] = (max-min)*((float)ix[i]/(float)maxint)+min;
 
576
    delete [] ix;
 
577
 
 
578
    return idx;
 
579
  }
 
580
 
 
581
 
 
582
/*!
 
583
**\fn OB_io_util_calc_NumBits(unsigned int *x, unsigned int N)
 
584
**\param x an unsigned integer array
 
585
**\paran N The number of values in the unsigned integer array x.
 
586
**\return The number of bits per value required to store the
 
587
**unsigned integer values in x with the 
 
588
**OB_io_write_binary_compressed(char*ccc, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
 
589
**and
 
590
**OB_io_write_binary_compressed(ostream& ostr, unsigned int *x, unsigned int NumBits, unsigned int NumInts)
 
591
** functions.
 
592
*/
 
593
unsigned int OB_io_util_calc_NumBits(unsigned int *x, unsigned int N)
 
594
  {
 
595
    if (!N) return 0;
 
596
    unsigned int i;
 
597
    unsigned int max=0;
 
598
    for (i=0 ; i<N ; i++) if (x[i] > max) max = x[i];
 
599
    unsigned int mmax=(unsigned int) 0;
 
600
    for (i=0 ; i<32 && max > mmax ; i++) mmax |= ((unsigned int)1)<<i;
 
601
    return i;
 
602
  }
 
603
 
 
604
/*!
 
605
**\fn OB_io_util_calc_NumBits(float *x, unsigned int N, float res)
 
606
**\param x A float array
 
607
**\param N The number of values in the float array x.
 
608
**\param The resolution desired.
 
609
**\returns The number of bits per value required to store float
 
610
**the float values in x at a resolution of res (or better) with the
 
611
**OB_io_write_binary_compressed(char*ccc, float *x, unsigned int NumBits, unsigned int Nfloats)
 
612
**or
 
613
**OB_io_write_binary_compressed(istream& istr, float *x, unsigned int NumBits, unsigned int Nfloats)
 
614
**functions.
 
615
*/
 
616
unsigned int OB_io_util_calc_NumBits(float *x, unsigned int N, float res)
 
617
  {
 
618
    if (!N) return 0;
 
619
 
 
620
    //Find max and min
 
621
    unsigned int i;
 
622
    float max = x[0];
 
623
    float min = x[0];
 
624
    for (i=0 ; i<N ; i++) {
 
625
        if (x[i] > max) max = x[i];
 
626
        if (x[i] < min) min = x[i];
 
627
      }
 
628
 
 
629
    unsigned int imax = (unsigned int) ((max-min)/res+0.5f);
 
630
    unsigned int mmax=(unsigned int) 0;
 
631
    for (i=0 ; i<32 && imax > mmax ; i++) mmax |= ((unsigned int)1)<<i;
 
632
    return i;
 
633
  }
 
634
 
 
635
 
 
636
/******************* Writing OBBinaryIO objects ************************/
 
637
ostream& operator<<(ostream& ostr, const OBBinaryIO& obj)
 
638
  {
 
639
    unsigned int size = obj.BinarySize();
 
640
    OB_io_write_binary(ostr,(const char*)&size,sizeof(unsigned int),1);
 
641
    obj.WriteBinary(ostr);
 
642
    return ostr;
 
643
  }
 
644
istream& operator>>(istream& istr, OBBinaryIO& obj)
 
645
  {
 
646
    unsigned int size;
 
647
    OB_io_read_binary(istr,(char*)&size,sizeof(unsigned int),1);
 
648
    unsigned int size2;
 
649
    size2 = obj.ReadBinary(istr);
 
650
    if (size != size2) {
 
651
        cerr << "WARNING operator>>(istream& istr, OBBinaryIO& obj) " << endl;
 
652
        cerr << "Record size (" << size << ") is not equal to number of bytes read (" << size2 << ")" << endl;
 
653
      }
 
654
    return istr;
 
655
  }
 
656
 
 
657
 
 
658
}// End namespace OpenBabel
 
659