gphys 1.5.6 → 1.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,6 +30,8 @@ enum bc_type {
30
30
  #define ID3o(i,j,k) ((i) + (j)*n0 + (k)*n0*n1o)
31
31
  #define ID3z(i,j,k) ((i) + (j)*n0 + (k)*n0*nz)
32
32
  #define ID3c(i,j,k) ((i) + (j)*n0 + (k)*n0*nc)
33
+ #define ID3e(i,j,k,ni,nj,nk) (((i)%(ni)) + (j)*(ni) + ((k)%(nk))*(ni)*(nj))
34
+ // ID3e: covers 1D case (if ni==1 or nk==1, i or k is neglected by %)
33
35
  #define ID2(i,j) ((i) + (j)*n0)
34
36
  #define ID5(i,j,k,l,m) ((i) + (j)*ni + (k)*ni*nd1 + (l)*ni*nd1*no1 + (m)*ni*nd1*no1*nd2)
35
37
  #define NMax(i,j) ( (i) >= (j) ? (i) : (j) )
@@ -853,13 +855,13 @@ bin_mean_sum(int argc, VALUE *argv, VALUE self, int mean)
853
855
  static VALUE
854
856
  bin_mean(int argc, VALUE *argv, VALUE self)
855
857
  {
856
- bin_mean_sum(argc, argv, self, 1);
858
+ return bin_mean_sum(argc, argv, self, 1);
857
859
  }
858
860
 
859
861
  static VALUE
860
862
  bin_sum(int argc, VALUE *argv, VALUE self)
861
863
  {
862
- bin_mean_sum(argc, argv, self, 0);
864
+ return bin_mean_sum(argc, argv, self, 0);
863
865
  }
864
866
 
865
867
 
@@ -1000,36 +1002,44 @@ is simply when w is z itself, which is exploited in implementation.
1000
1002
 
1001
1003
  */
1002
1004
  static VALUE
1003
- cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
1005
+ cell_integ_irreg(obj, f, mask, z, zdim, nzbound, ccell, w)
1004
1006
  VALUE obj;
1005
1007
  VALUE f; // [NArray] multi-D data to be integrated
1006
- VALUE z; // [NArray] multi-D coordinate values of f's grid; integration
1007
- // is always made along z (whether or not w is given)
1008
+ VALUE mask; // [nil, or NArray] if NArray, mask of f
1009
+ VALUE z; // [NArray] 1D or multi-D coordinate values of f's grid
1010
+ // (if 1D, its length must be f's along zdim;
1011
+ // if multi-D z.shape must be equal to f.shape).
1012
+ // integration is always along z (whether or not w is given)
1008
1013
  VALUE zdim; // [Integer] dimension of f along which to integrate
1009
1014
  VALUE nzbound; // [nil, or NArray(integer) with rank 1 smaller than f's]
1010
1015
  // Length of the actual z dim for each column (data must
1011
1016
  // be packed from the beginning of z dim; 0...nzbound[j,l]).
1012
1017
  // If nil, the entire column is assumed valid;
1013
- VALUE ccell; // [NArray] 1D grid to sample the result. It is the z
1014
- // coordinate if w is nil; if w is given, it's a w grid.
1018
+ VALUE ccell; // [NArray] 1D grid to sample the result.
1019
+ // (if multi-D, its shape except along zdim must be f's);
1020
+ // It is the z coordinate if w is nil;
1021
+ // if w is given, it's a w grid.
1015
1022
  VALUE w; // [nil or NArray] alternative grid point values to express
1016
1023
  // the result as a function of w rather than z (special case)
1017
1024
  // (e.g. z: pressure/g; w: potential temperature)
1018
1025
  {
1019
1026
  struct NARRAY *na;
1020
- int rank, zd, d;
1027
+ int rank, zd, d, with_mask;
1021
1028
  na_shape_t *shape;
1022
1029
  na_shape_t n0, nz, n2, nzw;
1030
+ na_shape_t n0z, n2z, n0w, n2w, n0c, n2c;
1023
1031
  na_shape_t *oshape, nc;
1024
1032
  VALUE F; // the result: \int f dz
1025
1033
  double *fv, *zv, *wc, *wv, *Fv;
1026
1034
  int32_t *nzbd;
1035
+ u_int8_t *msk;
1027
1036
  na_shape_t j, k, l, m; // k: index of z (orig); m: index of ccell
1028
1037
  double fa, fb, dz, wa, wb, wac, wbc, a, b, fi;
1029
1038
 
1030
1039
  // cast to ensure pointer types
1031
1040
 
1032
1041
  if(!IsNArray(f)) rb_raise(rb_eArgError, "f is not a NArray");
1042
+ if(mask!=Qnil && !IsNArray(mask)) rb_raise(rb_eArgError, "mask is must be nil or a NArray");
1033
1043
  if(!IsNArray(z)) rb_raise(rb_eArgError, "z is not a NArray");
1034
1044
  if(!IsNArray(ccell)) rb_raise(rb_eArgError, "ccell is not a NArray");
1035
1045
  if(w!=Qnil && !IsNArray(w)) rb_raise(rb_eArgError, "w is must be nil or a NArray");
@@ -1043,9 +1053,6 @@ cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
1043
1053
  // read & check the shapes
1044
1054
 
1045
1055
  rank = NA_RANK(f);
1046
- if ( NA_RANK(z) != rank ){
1047
- rb_raise(rb_eArgError, "f and z must have the same shape");
1048
- }
1049
1056
  if ( nzbound != Qnil && NA_RANK(nzbound) != rank-1 ){
1050
1057
  rb_raise(rb_eArgError, "rank of nzbound must be 1 smaller than f's");
1051
1058
  }
@@ -1068,17 +1075,61 @@ cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
1068
1075
  n2 *= shape[d];
1069
1076
  }
1070
1077
 
1071
- if (NA_TOTAL(z) != n0*nz*n2){
1072
- rb_raise(rb_eArgError, "lengths of f and z do not agree");
1078
+ if(mask==Qnil) {
1079
+ with_mask = 0;
1080
+ msk = NULL;
1081
+ } else {
1082
+ with_mask = 1;
1083
+ if (NA_TOTAL(mask) != n0*nz*n2){
1084
+ rb_raise(rb_eArgError, "lengths of f and mask must agree");
1085
+ }
1086
+ GetNArray(mask, na);
1087
+ msk = (u_int8_t *)NA_PTR(na, 0);
1073
1088
  }
1089
+
1090
+ if ( NA_RANK(z) == rank ){
1091
+ if (NA_TOTAL(z) != n0*nz*n2){
1092
+ rb_raise(rb_eArgError, "lengths of f and z must agree (if multiD)");
1093
+ }
1094
+ n0z = n0;
1095
+ n2z = n2;
1096
+ } else if (NA_RANK(z) == 1) {
1097
+ if (NA_TOTAL(z) != nz){
1098
+ rb_raise(rb_eArgError, "lengths of z must be nz (if 1D)");
1099
+ }
1100
+ n0z = 1;
1101
+ n2z = 1;
1102
+ } else {
1103
+ rb_raise(rb_eArgError, "z must have the same rank with f or be 1D");
1104
+ }
1105
+
1074
1106
  if (nzbound != Qnil && NA_TOTAL(nzbound) != n0*n2){
1075
1107
  rb_raise(rb_eArgError, "shapes of f and nzbound are incompatible");
1076
1108
  }
1077
1109
 
1078
1110
  // prepare the output array; assign pointers
1079
1111
 
1080
- if ( NA_RANK(ccell) != 1 ){rb_raise(rb_eArgError, "ccell is not 1D");}
1081
- nc = NA_TOTAL(ccell);
1112
+ if ( NA_RANK(ccell) == 1 ){
1113
+ nc = NA_TOTAL(ccell);
1114
+ n0c = 1;
1115
+ n2c = 1;
1116
+ } else if (NA_RANK(ccell) == rank) {
1117
+ GetNArray(ccell, na);
1118
+ shape = na->shape;
1119
+ for (d=0, n0c=1 ; d<zd ; d++){
1120
+ n0c *= shape[d];
1121
+ }
1122
+ nc = shape[zd];
1123
+ for (d=zd+1, n2c=1 ; d<rank ; d++){
1124
+ n2c *= shape[d];
1125
+ }
1126
+ if (n0c != n0) rb_raise(rb_eArgError,
1127
+ "shape miss match btwn f and ccell (case 0)");
1128
+ if (n2c != n2) rb_raise(rb_eArgError,
1129
+ "shape miss match btwn f and ccell (case 2)");
1130
+ } else {
1131
+ rb_raise(rb_eArgError, "ccell is must be 1D or f.rank");
1132
+ }
1082
1133
  oshape = ALLOCA_N(na_shape_t, rank);
1083
1134
  for (d=0; d<rank ; d++){
1084
1135
  if (d != zd){
@@ -1105,15 +1156,32 @@ cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
1105
1156
 
1106
1157
  GetNArray(ccell, na);
1107
1158
  wc = (double *)NA_PTR(na, 0);
1108
- if (wc[0] > wc[nc-1]){
1159
+ if (wc[ID3e(0,0,0,n0c,nc,n2c)] > wc[ID3e(0,nc-1,0,n0c,nc,n2c)]){
1109
1160
  rb_raise(rb_eArgError, "ccell must be alined in the increasing order");
1110
1161
  }
1111
1162
 
1112
1163
  if(w != Qnil){
1113
1164
  GetNArray(w, na);
1114
1165
  wv = (double *)NA_PTR(na, 0);
1166
+ if ( NA_RANK(w) == rank ){
1167
+ if (NA_TOTAL(w) != n0*nz*n2){
1168
+ rb_raise(rb_eArgError, "lengths of f and w must agree (if multiD)");
1169
+ }
1170
+ n0w = n0;
1171
+ n2w = n2;
1172
+ } else if (NA_RANK(w) == 1) {
1173
+ if (NA_TOTAL(w) != nz){
1174
+ rb_raise(rb_eArgError, "lengths of z must be nz (if 1D)");
1175
+ }
1176
+ n0w = 1;
1177
+ n2w = 1;
1178
+ } else {
1179
+ rb_raise(rb_eArgError, "z must have the same rank with f or be 1D");
1180
+ }
1115
1181
  } else {
1116
1182
  wv = zv;
1183
+ n0w = n0z;
1184
+ n2w = n2z;
1117
1185
  }
1118
1186
 
1119
1187
  // main loop
@@ -1130,24 +1198,27 @@ cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
1130
1198
  m=0; // m: index of the new cooridnate
1131
1199
  for (k=0; k<nzw-1; k++){
1132
1200
  // set the trapezoid
1133
- if (wv[ID3z(j,k,l)] < wv[ID3z(j,k+1,l)]) {
1134
- wa = wv[ID3z(j,k,l)]; // "left" (lower) end along w
1135
- wb = wv[ID3z(j,k+1,l)]; // "right" (upper) end along w
1201
+ if (wv[ID3e(j,k,l,n0w,nz,n2w)] < wv[ID3e(j,k+1,l,n0w,nz,n2w)]) {
1202
+ wa = wv[ID3e(j,k,l,n0w,nz,n2w)]; // left/lower end along w
1203
+ wb = wv[ID3e(j,k+1,l,n0w,nz,n2w)]; //right/upper end along w
1136
1204
  fa = fv[ID3z(j,k,l)]; // at the left end
1137
1205
  fb = fv[ID3z(j,k+1,l)]; // at the right end
1138
1206
  } else {
1139
- wa = wv[ID3z(j,k+1,l)]; // "left" (lower) end along w
1140
- wb = wv[ID3z(j,k,l)]; // "right" (upper) end along w
1207
+ wa = wv[ID3e(j,k+1,l,n0w,nz,n2w)]; // left/lower end along w
1208
+ wb = wv[ID3e(j,k,l,n0w,nz,n2w)]; //right/upper end along w
1141
1209
  fa = fv[ID3z(j,k+1,l)]; // at the left end
1142
1210
  fb = fv[ID3z(j,k,l)]; // at the right end
1143
1211
  }
1144
- dz = fabs(zv[ID3z(j,k+1,l)]-zv[ID3z(j,k,l)]);
1212
+ if ( with_mask && (!msk[ID3z(j,k,l)] || !msk[ID3z(j,k+1,l)]) ) {
1213
+ fa = fb = 0.0;
1214
+ }
1215
+ dz = fabs(zv[ID3e(j,k+1,l,n0z,nz,n2z)]-zv[ID3e(j,k,l,n0z,nz,n2z)]);
1145
1216
 
1146
1217
  // find the right next grid point to wa (left end)
1147
- if (wa < wc[m]){
1148
- while( m>0 && wa < wc[m-1] ){ m--; }
1218
+ if (wa < wc[ID3e(j,m,l,n0c,nc,n2c)]){
1219
+ while( m>0 && wa < wc[ID3e(j,m-1,l,n0c,nc,n2c)] ){ m--; }
1149
1220
  } else {
1150
- while( wa >= wc[m] && m<nc ){ m++; }
1221
+ while( wa >= wc[ID3e(j,m,l,n0c,nc,n2c)] && m<nc ){ m++; }
1151
1222
  // m can be nc, meaning the entire trapezoid is outside
1152
1223
  }
1153
1224
 
@@ -1156,7 +1227,7 @@ cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
1156
1227
  wac = wa; // left end of the current bin
1157
1228
  while(1){
1158
1229
  //wbc = (wb<=wc[m]) ? wb : wc[m]; // current right end
1159
- wbc = fmin(wb, wc[m]);
1230
+ wbc = fmin(wb, wc[ID3e(j,m,l,n0c,nc,n2c)]);
1160
1231
 
1161
1232
  // do the integration
1162
1233
  if (wb != wa){
@@ -1168,8 +1239,8 @@ cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
1168
1239
  }
1169
1240
  // ^ f value at (a+b)/2 ^ width
1170
1241
  Fv[ID3c(j,m,l)] += fi;
1171
- if ( wb <= wc[m] || m == nc-1 ) break;
1172
- wac = wc[m];
1242
+ if ( wb <= wc[ID3e(j,m,l,n0c,nc,n2c)] || m == nc-1 ) break;
1243
+ wac = wc[ID3e(j,m,l,n0c,nc,n2c)];
1173
1244
  m++;
1174
1245
  }
1175
1246
  } else {
@@ -1189,8 +1260,9 @@ cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
1189
1260
  axis. -- This method acutually uses cell_integ_irreg and make sumation.
1190
1261
  */
1191
1262
  static VALUE
1192
- cum_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
1263
+ cum_integ_irreg(obj, f, mask, z, zdim, nzbound, ccell, w)
1193
1264
  VALUE obj;
1265
+ VALUE mask; // [nil, or NArray] if NArray, mask of f
1194
1266
  VALUE f;
1195
1267
  VALUE z;
1196
1268
  VALUE zdim;
@@ -1200,7 +1272,7 @@ cum_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
1200
1272
  {
1201
1273
  VALUE F;
1202
1274
 
1203
- F = cell_integ_irreg(obj, f, z, zdim, nzbound, ccell, w);
1275
+ F = cell_integ_irreg(obj, f, mask, z, zdim, nzbound, ccell, w);
1204
1276
  cum_sum_dfloat_bang(obj, F, zdim);
1205
1277
  return F;
1206
1278
  }
@@ -1233,7 +1305,7 @@ cum_integ_irreg(obj, f, z, zdim, nzbound, ccell, w)
1233
1305
 
1234
1306
  */
1235
1307
  static VALUE
1236
- cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
1308
+ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb, misval)
1237
1309
  VALUE obj;
1238
1310
  VALUE f; // [NArray] multi-D data
1239
1311
  VALUE zdim; // [Integer] dimension of zcrd in f
@@ -1241,15 +1313,17 @@ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
1241
1313
  VALUE upper; // true/false to cap the upper/lower side (with z)
1242
1314
  VALUE zb; // [NArray] the "surface" z; zb.rank must be f.rank-1
1243
1315
  VALUE fb; // [nil or NArray] the f value at surface (zb.shape==fb.shape)
1316
+ VALUE misval; // [nil or Float] if Float, missing value of f
1244
1317
  {
1245
1318
  VALUE fe; // [NArray] return value, extended f by fb
1246
1319
  VALUE ze; // [NArray] return value, grid points of fe along zdim
1247
1320
  VALUE nze; // [NArray] return value, valid data lengths along zdim in fe
1248
1321
  VALUE result; // [Array] [fe, ze, nze] (return the two in an Array)
1249
1322
  struct NARRAY *na;
1250
- int rank, zd, d;
1323
+ int rank, zd, d, w_mis, mis;
1251
1324
  na_shape_t n0, nz, n2, nc;
1252
1325
  double *fv, *zcv, *zbv, *fbv, *fev, *zev;
1326
+ double ze_filv, rmis;
1253
1327
  int32_t *nzev;
1254
1328
  int zcincr, capupper, sgn;
1255
1329
  na_shape_t j, k, l;
@@ -1266,11 +1340,15 @@ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
1266
1340
  zcrd = na_cast_object(zcrd, NA_DFLOAT);
1267
1341
  zb = na_cast_object(zb, NA_DFLOAT);
1268
1342
  if(fb != Qnil){ fb = na_cast_object(fb, NA_DFLOAT); }
1343
+ w_mis = (misval != Qnil);
1344
+ if (w_mis) {
1345
+ rmis = NUM2DBL(misval);
1346
+ }
1269
1347
 
1270
1348
  // read & check
1271
1349
 
1272
1350
  rank = NA_RANK(f);
1273
- if (NA_RANK(zb)!=rank-1){rb_raise(rb_eArgError, "zb.rank must f.rank-1");}
1351
+ if (NA_RANK(zb)!=rank-1){rb_raise(rb_eArgError,"zb.rank must be f.rank-1");}
1274
1352
 
1275
1353
  zd = NUM2INT(zdim);
1276
1354
  if (zd < 0) zd += rank; // negative: count from the last dim
@@ -1316,6 +1394,11 @@ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
1316
1394
  rb_raise(rb_eArgError,"Unexpected data alignment: To ensure that the zdim dimension of the output NArray (fe, ze) starts from the valid data (i.e., its beginning is inside the domain), it should be either that zcrd is increasing and upper==true or that zcrd is decreasing and upper==false");
1317
1395
  }
1318
1396
 
1397
+ if (capupper) {
1398
+ ze_filv = 1e200;
1399
+ } else {
1400
+ ze_filv = -1e200;
1401
+ }
1319
1402
  // prepare the output array
1320
1403
 
1321
1404
  nc = nz+1;
@@ -1355,7 +1438,7 @@ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
1355
1438
  }
1356
1439
  for (j=0; j<n0; j++){
1357
1440
  fev[ID3c(j,nc-1,l)] = 0e0; // clear
1358
- zev[ID3c(j,nc-1,l)] = 0e0; // clear
1441
+ zev[ID3c(j,nc-1,l)] = ze_filv; // clear
1359
1442
  }
1360
1443
  }
1361
1444
 
@@ -1364,7 +1447,8 @@ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
1364
1447
  for (l=0; l<n2; l++){
1365
1448
  for (j=0; j<n0; j++){
1366
1449
  for (k=0; k<nz; k++){
1367
- if ( (zcv[k] - zbv[ID2(j,l)])*sgn > 0 ){
1450
+ mis = (w_mis && fv[ID3z(j,k,l)] == rmis);
1451
+ if ( mis || (zcv[k] - zbv[ID2(j,l)])*sgn > 0 ){
1368
1452
  fev[ID3c(j,k,l)] = fbv[ID2(j,l)];
1369
1453
  zev[ID3c(j,k,l)] = zbv[ID2(j,l)];
1370
1454
  nzev[ID2(j,l)] = k+1;
@@ -1383,12 +1467,13 @@ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
1383
1467
  for (l=0; l<n2; l++){
1384
1468
  for (j=0; j<n0; j++){
1385
1469
  for (k=0; k<nz; k++){
1386
- if ( (zcv[k] - zbv[ID2(j,l)])*sgn > 0 ){
1387
- //fev[ID3c(j,k,l)] = fv[ID3z(j,k-1,l)];//naive extension
1388
- fev[ID3c(j,k,l)] =
1389
- ( fv[ID3z(j,k-1,l)]*(zcv[k]-zbv[ID2(j,l)])
1390
- + fv[ID3z(j,k,l)]*(zbv[ID2(j,l)]-zcv[k-1]) ) /
1391
- (zcv[k] - zcv[k-1]);
1470
+ mis = (w_mis && fv[ID3z(j,k,l)] == rmis);
1471
+ if ( mis || (zcv[k] - zbv[ID2(j,l)])*sgn > 0 ){
1472
+ fev[ID3c(j,k,l)] = fv[ID3z(j,k-1,l)];//naive extension
1473
+ //fev[ID3c(j,k,l)] =
1474
+ // ( fv[ID3z(j,k-1,l)]*(zcv[k]-zbv[ID2(j,l)])
1475
+ // + fv[ID3z(j,k,l)]*(zbv[ID2(j,l)]-zcv[k-1]) ) /
1476
+ // (zcv[k] - zcv[k-1]);
1392
1477
  zev[ID3c(j,k,l)] = zbv[ID2(j,l)];
1393
1478
  nzev[ID2(j,l)] = k+1;
1394
1479
  break;
@@ -1409,6 +1494,211 @@ cap_by_boundary(obj, f, zdim, zcrd, upper, zb, fb)
1409
1494
  return result;
1410
1495
  }
1411
1496
 
1497
+ /*
1498
+ c_val_crossing (C extension): find the positions or the values of y where the values of z crosses zval along dim (using the linear interpolation)
1499
+
1500
+ ARGUMENT
1501
+ * z [NArray of float or sfloat]
1502
+ * zmask [nil or NArray byte]
1503
+ * dim [Integer]
1504
+ * zval [Numeric]
1505
+ * y [nil or NArray of float or sfloat] if nil, dim indices are used
1506
+ * nth [Integer] 1,2,3,... for the 1st, 2nd, 3rd,... crossing
1507
+ * descend [true, false, or nil] true: inspect dim indices from the last
1508
+ * incr [nil, true, or false] nil: any crsossing is detected; true:
1509
+ only increasing crossing is detected; false: only decreasing crossing is ..
1510
+
1511
+ RETURN VALUE
1512
+ * yc [NArray double or float] : value of y at the crossing
1513
+ * ycmask [NArray byte]: mask Array to create NArrayMiss from yc & ycmask
1514
+ */
1515
+ static VALUE
1516
+ val_crossing(obj, z, zmask, dim, zval, y, nth, descend, incr)
1517
+ VALUE obj;
1518
+ VALUE z;
1519
+ VALUE zmask;
1520
+ VALUE dim;
1521
+ VALUE zval;
1522
+ VALUE y;
1523
+ VALUE nth;
1524
+ VALUE descend;
1525
+ VALUE incr;
1526
+ {
1527
+ VALUE yc; // return value 1 (NArray)
1528
+ VALUE ycmask; // return value 2 (NArray byte)
1529
+ double *yc_d;
1530
+ float *yc_f;
1531
+ u_int8_t *ycmsk;
1532
+ int rank, dm, d, y1d;
1533
+ struct NARRAY *na;
1534
+ na_shape_t *shape, *oshape;
1535
+ double *z_d, *y_d, zcv, z1, z2;
1536
+ float *z_f, *y_f;
1537
+ int zmis;
1538
+ u_int8_t *zmsk;
1539
+ na_shape_t n0, n1, n2;
1540
+ na_shape_t j, k, l;
1541
+ double a; // fractional position: 0<=a<=1
1542
+ na_shape_t kf, ke, kstp;
1543
+ int zdbl, ydbl;
1544
+ int ith, nthv;
1545
+ int icross, dcross;
1546
+ double fillv = 9.9692099683868690e+36; // from NetCDF
1547
+
1548
+ if (!IsNArray(z)) {rb_raise(rb_eArgError, "z must be a NArray");}
1549
+ if (y!= Qnil && !IsNArray(y)) {
1550
+ rb_raise(rb_eArgError, "y must be nill or a NArray");
1551
+ }
1552
+
1553
+ rank = NA_RANK(z);
1554
+ GetNArray(z, na);
1555
+ shape = na->shape;
1556
+
1557
+ if ( NA_TYPE(z) == NA_DFLOAT) {
1558
+ zdbl = 1; // true
1559
+ z_d = (double *)NA_PTR(na, 0);
1560
+ } else if (NA_TYPE(z) == NA_SFLOAT) {
1561
+ zdbl = 0; // false
1562
+ z_f = (float *)NA_PTR(na, 0);
1563
+ } else {
1564
+ rb_raise(rb_eArgError, "z must be a DFLOAT or SFLOAT NArray");
1565
+ }
1566
+
1567
+ if (zmask == Qnil) {
1568
+ zmis = 0; // no need to consider data missing;
1569
+ } else {
1570
+ if (!IsNArray(zmask)) {rb_raise(rb_eArgError, "zmask is not a NArray");}
1571
+ zmis = 1; // data missing may exist
1572
+ GetNArray(zmask, na);
1573
+ zmsk = (u_int8_t *)NA_PTR(na, 0);
1574
+ }
1575
+
1576
+
1577
+ dm = NUM2INT(dim);
1578
+ if (dm < 0) dm += rank; // negative: count from the last dim
1579
+
1580
+ if (dm < 0 || dm >= rank){
1581
+ rb_raise(rb_eArgError,
1582
+ "Invalid dimension (%d) for a rank %d NArray", NUM2INT(dim), rank);
1583
+ }
1584
+
1585
+ zcv = NUM2DBL(zval);
1586
+
1587
+ oshape = ALLOCA_N(na_shape_t, rank-1);
1588
+ for (d=0, n0=1 ; d<dm ; d++){
1589
+ n0 *= shape[d];
1590
+ oshape[d] = shape[d];
1591
+ }
1592
+ n1 = shape[dm];
1593
+ for (d=dm+1, n2=1 ; d<rank ; d++){
1594
+ n2 *= shape[d];
1595
+ oshape[d-1] = shape[d];
1596
+ }
1597
+
1598
+ if ( descend == Qtrue ){
1599
+ kf = n1-1;
1600
+ ke = -1;
1601
+ kstp = -1;
1602
+ } else {
1603
+ kf = 0;
1604
+ ke = n1;
1605
+ kstp = 1;
1606
+ }
1607
+
1608
+ if ( incr == Qnil ){
1609
+ icross = 1;
1610
+ dcross = 1;
1611
+ } else if ( incr == Qtrue ){
1612
+ icross = 1;
1613
+ dcross = 0;
1614
+ } else {
1615
+ icross = 0;
1616
+ dcross = 1;
1617
+ }
1618
+
1619
+ nthv = NUM2INT(nth);
1620
+ if (nthv <= 0) {
1621
+ rb_raise(rb_eArgError, "nth (%d) must be positive (1,2,...)", nthv);
1622
+ }
1623
+
1624
+ if ( y == Qnil ) {
1625
+ ydbl = 1; // true
1626
+ y1d = 1; // true
1627
+ y_d = ALLOCA_N(double, n1);
1628
+ for (k=0; k<n1; k++) {y_d[k] = (double) k;}
1629
+ } else {
1630
+ GetNArray(y, na);
1631
+ if ( NA_TYPE(y) == NA_DFLOAT) {
1632
+ ydbl = 1; // true
1633
+ y_d = (double *)NA_PTR(na, 0);
1634
+ } else if (NA_TYPE(y) == NA_SFLOAT) {
1635
+ ydbl = 0; // false
1636
+ y_f = (float *)NA_PTR(na, 0);
1637
+ } else {
1638
+ rb_raise(rb_eArgError, "expects a DFLOAT or SFLOAT NArray");
1639
+ }
1640
+ if (NA_TOTAL(y) == n1) {
1641
+ // treated as 1D along dim
1642
+ y1d = 1; // true
1643
+ } else if (NA_TOTAL(y) == NA_TOTAL(z)) {
1644
+ // treated as y and z share a shape
1645
+ y1d = 0; // false
1646
+ } else {
1647
+ rb_raise(rb_eArgError, "Shape (length) of y mismatches that of z");
1648
+ }
1649
+ }
1650
+
1651
+ if (ydbl) {
1652
+ yc = na_make_object(NA_DFLOAT, rank-1, oshape, cNArray);
1653
+ yc_d = NA_PTR_TYPE(yc, double *);
1654
+ for (j=0; j<n0*n2; j++){yc_d[j] = fillv;}
1655
+ } else {
1656
+ yc = na_make_object(NA_SFLOAT, rank-1, oshape, cNArray);
1657
+ yc_f = NA_PTR_TYPE(yc, float *);
1658
+ for (j=0; j<n0*n2; j++){yc_f[j] = (float) fillv;}
1659
+ }
1660
+ ycmask = na_make_object(NA_BYTE, rank-1, oshape, cNArray);
1661
+ ycmsk = NA_PTR_TYPE(ycmask, u_int8_t *);
1662
+ for (j=0; j<n0*n2; j++){ycmsk[j] = 0;}
1663
+
1664
+ for (l=0; l<n2; l++){
1665
+ for (j=0; j<n0; j++){
1666
+ z1 = ( zdbl ? z_d[ID3(j,kf,l)] : z_f[ID3(j,kf,l)] );
1667
+ ith = 0;
1668
+ for (k=kf+kstp; k!=ke; k+=kstp) {
1669
+ z2 = ( zdbl ? z_d[ID3(j,k,l)] : z_f[ID3(j,k,l)] );
1670
+ if ( ( !zmis || (zmsk[ID3(j,k-kstp,l)] && zmsk[ID3(j,k,l)]) ) &&
1671
+ ( icross && z1<zcv && zcv<=z2 ||
1672
+ dcross && z1>zcv && zcv>=z2 ) ){
1673
+ ith++;
1674
+ if (ith == nthv){
1675
+ a = (zcv-z1) / (z2-z1);
1676
+ if (y1d) {
1677
+ if (ydbl) {
1678
+ yc_d[ID2(j,l)] = (1.0-a)*y_d[k-kstp] + a*y_d[k];
1679
+ } else {
1680
+ yc_f[ID2(j,l)] = (1.0-a)*y_f[k-kstp] + a*y_f[k];
1681
+ }
1682
+ } else {
1683
+ if (ydbl) {
1684
+ yc_d[ID2(j,l)] = (1.0-a)*y_d[ID3(j,k-kstp,l)]
1685
+ + a*y_d[ID3(j,k,l)];
1686
+ } else {
1687
+ yc_f[ID2(j,l)] = (1.0-a)*y_f[ID3(j,k-kstp,l)]
1688
+ + a*y_f[ID3(j,k,l)];
1689
+ }
1690
+ }
1691
+ ycmsk[ID2(j,l)] = 1;
1692
+ break;
1693
+ }
1694
+ }
1695
+ z1 = z2;
1696
+ }
1697
+ }
1698
+ }
1699
+ return rb_ary_new3(2, yc, ycmask);
1700
+ }
1701
+
1412
1702
  void
1413
1703
  init_gphys_dim_op()
1414
1704
  {
@@ -1432,9 +1722,11 @@ init_gphys_dim_op()
1432
1722
  rb_define_singleton_method(cGPhys, "c_bin_sum", bin_sum, -1);
1433
1723
 
1434
1724
  rb_define_private_method(cVArray, "c_cum_sum", cum_sum, 2);
1725
+ rb_define_singleton_method(cGPhys, "c_cum_sum", cum_sum, 2);
1435
1726
  rb_define_singleton_method(cGPhys, "c_cell_integ_irreg",
1436
- cell_integ_irreg, 6);
1437
- rb_define_singleton_method(cGPhys, "c_cum_integ_irreg", cum_integ_irreg, 6);
1727
+ cell_integ_irreg, 7);
1728
+ rb_define_singleton_method(cGPhys, "c_cum_integ_irreg", cum_integ_irreg, 7);
1438
1729
 
1439
- rb_define_singleton_method(cGPhys, "c_cap_by_boundary", cap_by_boundary, 6);
1730
+ rb_define_singleton_method(cGPhys, "c_cap_by_boundary", cap_by_boundary, 7);
1731
+ rb_define_singleton_method(cGPhys, "c_val_crossing", val_crossing, 8);
1440
1732
  }
@@ -1,3 +1,9 @@
1
+ void init_ext_coord();
2
+ void init_gphys_interpo();
3
+ void init_gphys_multibitIO();
4
+ void init_gphys_dim_op();
5
+ void init_gphys_quad_mesh_sample();
6
+
1
7
  void
2
8
  Init_gphys_ext()
3
9
  {