File: valpina.c

package info (click to toggle)
emoslib 000380%2Bdfsg-3
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 47,712 kB
  • ctags: 11,551
  • sloc: fortran: 89,643; ansic: 24,200; makefile: 370; sh: 355
file content (241 lines) | stat: -rwxr-xr-x 6,894 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/**
* Copyright 1981-2007 ECMWF
* 
* Licensed under the GNU Lesser General Public License which
* incorporates the terms and conditions of version 3 of the GNU
* General Public License.
* See LICENSE and gpl-3.0.txt for details.
*/

#include <stdio.h>
#include "fortint.h"

#define CHARSIZE (long) (sizeof(char)*8)
#define LEASTSIGBIT 0x01

long bitmapValue(unsigned char * , long );
long bitmapValueTotal(unsigned char * , long, long );
fortint valpina(unsigned char * , fortint *, fortint * );
fortint valpina_(unsigned char * , fortint *, fortint * );
long separationBetweenValues(unsigned char * , long , long );
fortint numvals(unsigned char *, fortint *, fortint *);
fortint numvals_(unsigned char *, fortint *, fortint *);
fortint onebits(unsigned char *, fortint *);
fortint onebits_(unsigned char *, fortint *);

fortint numvals_(unsigned char * grib, fortint* istart, fortint* ifinish) {
/*
// Returns a count of the number of 1s in a GRIB between positions
// 'start' and 'finish'.
// If start = 0, the static values in the function are initialised.
*/
long start = (long) (*istart);
long finish = (long) (*ifinish);
static long oldTotal;
static long oldStart, oldFinish;
unsigned char * bitmap = grib;
static unsigned char * oldBitmap = 0;

  if( !start ) {
    oldBitmap = 0;
    oldTotal = 0;
    oldStart = oldFinish = 1;
    return (fortint) oldTotal;
  }

  if( oldBitmap != bitmap ) {
    oldBitmap = bitmap;
    oldStart = oldFinish = 1;
    oldTotal = 0;
  }

  if( start == finish ) {
    oldStart = oldFinish = finish;
    oldTotal = 0;
    return (fortint) oldTotal;
  }

  if( oldStart != start ) {
    oldTotal = bitmapValueTotal(bitmap, start+1, finish);
  }
  else {
    if( oldFinish < finish )
      oldTotal += bitmapValueTotal(bitmap, oldFinish+1, finish);
    else if( oldFinish > finish )
      oldTotal -= bitmapValueTotal(bitmap, finish+1, oldFinish);
  }

  oldStart = start;
  oldFinish = finish;

  return (fortint) oldTotal;

}

fortint numvals(unsigned char * grib, fortint* istart, fortint* ifinish) {
  return numvals_(grib,istart,ifinish);
}

fortint onebits_(unsigned char * grib, fortint* isection_3_offset) {
/*
// Returns a count of the number of 1s in a GRIB section 3 bitmap.
*/
long section_3_offset = (long) (*isection_3_offset);
unsigned char * bitmap = grib + section_3_offset;
long length, unused;
long number_of_bits, total;

  length = (*bitmap)<<16 | (*(bitmap+1)<<8) | *(bitmap+2);
  unused = *(bitmap+3);
  number_of_bits = ((length-6)*CHARSIZE) - unused;

  total = bitmapValueTotal((bitmap+6),1,number_of_bits);
  return ( (fortint) total );
}

fortint onebits(unsigned char * grib, fortint* isection_3_offset) {
  return onebits_(grib,isection_3_offset);
}

long bitmapValueTotal(unsigned char * bitmap, long start, long finish) {
/*
// Returns the count of 1 bits between start and finish in a bitmap.
*/
long total = 0;
unsigned char * first, * last, * next;
/*
  Lookup table to count number of 1s in a char
*/
static const char lookup[256] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
                                 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
                                 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
                                 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
                                 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
                                 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
                                 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
                                 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
                                 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
                                 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
                                 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
                                 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
                                 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
                                 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
                                 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
                                 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};
/*
  Masks to remove bits from left- and right-hand end of a char
*/
static const unsigned char bottomMask[8] =
  {0xff,0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x01};
static const unsigned char topMask[8]    =
  {0xff,0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80};
int bitsToAdd, bitsToSubtract;

  first = bitmap + (start-1)/CHARSIZE;
  last  = bitmap + (finish-1)/CHARSIZE;


  bitsToAdd = (start-1)%CHARSIZE;
  total = lookup[(*first & bottomMask[bitsToAdd])];

  for( next = (first+1); next < last ; next++ )
    total += lookup[*next];

  if( last > first ) total += lookup[*last];

  bitsToSubtract = CHARSIZE - 1 - (finish-1)%CHARSIZE;
  total -= lookup[(*last & (~topMask[bitsToSubtract]))];

  return total;
}

long bitmapValue(unsigned char * bitmap, long index) {
/*
// Returns the value (0,1) of the bit at position 'index' in a bitmap.
*/
unsigned char * next;
int bitShift;

  next = bitmap + (index-1)/CHARSIZE;
  bitShift = CHARSIZE - 1 - ((index-1)%CHARSIZE);

  return  (((*next) >> bitShift) & LEASTSIGBIT);

}

fortint valpina_(unsigned char * grib, fortint* ioffset, fortint* iindex) {
/*
//  A GRIB product starts at 'grib' and contains missing/non-missing values
//  as described by a bitmap which is at position 'offset' in the GRIB.
//
//  'index' is the position of a point (missing/non-missing) in the field.
//  If index = 0, the static values in the function are initialised.
//
//  Examines the bitmap and returns:
//
//  - the actual index of a non-missing value
//
//  - 0 for a missing value
*/
long offset = (long) (*ioffset);
long index = (long) (*iindex);
unsigned char * bitmap = (grib + offset);
static unsigned char * oldBitmap;
static long count = 0;
static long oldIndex = 0;
long value;

  if( !(index) ) {
    oldBitmap = 0;
    count = 0;
    oldIndex = 0;
    return (fortint) 0;
  }

  if( oldBitmap != bitmap ) {
    oldBitmap = bitmap;
    count = 0;
    oldIndex = 0;
  }

  value = bitmapValue(bitmap, index);

  if( value ) {
    if( (index) != oldIndex ) {
      count += separationBetweenValues(bitmap, oldIndex, index);
      oldIndex = index;
    }
    return (fortint) count;
  }
  else
    return (fortint) 0;
}

fortint valpina(unsigned char * grib, fortint* ioffset, fortint* iindex) {
  return valpina_(grib,ioffset,iindex);
}

long separationBetweenValues(unsigned char * bitmap,long oldIndex,long index) {
/*
//  Counts the number of actual (non-missing) values between two locations
//  in the bitmap given by 'index' and 'oldIndex'.
//
//  The returned count can be positive or negative depending on whether
//  index is after or before oldIndex.
*/
long start, finish, sign = 1, total = 0;

  if( index > oldIndex ) {
    start = oldIndex;
    finish = index;
  }
  else {
    start = index;
    finish = oldIndex;
    sign = -1;
  }

  total = bitmapValueTotal(bitmap, (start+1), finish);

  return (sign*total);
}