/* interpo.c : Extention library regarding interpolation of GPhys */ #include #include #include "ruby.h" #include "narray.h" #ifndef RARRAY_PTR # define RARRAY_PTR(ary) (RARRAY(ary)->ptr) #endif #ifndef RARRAY_LEN # define RARRAY_LEN(ary) (RARRAY(ary)->len) #endif static VALUE interpo_do(obj, shape_to, idxmap, val_from, missval, extrapo) VALUE obj; VALUE shape_to; // [Array] shape of the new grid VALUE idxmap; // [Array] index mapping VALUE val_from; // [NArray] values to be interpolated VALUE missval; // [nil or Float] missing value if Float VALUE extrapo; // [false/true] whether to extrapolate { VALUE val_to; VALUE chk , ary; struct NARRAY *naf; VALUE vm; int natype; int *sht; // shape to (could be size_t if NArray is changed) int *shf; // shape from (could be size_t if NArray is changed) size_t cshf; size_t rankf, rankt, lent; double *pt, *pf; int nomiss; double vmiss; int extr; size_t i, it, kf, j, k, l; int *mtyp; size_t *dm, *dm2, *dm2f, *dm3, *dm3f, *dm4, *dm4f; int **di, nid, nic; double **df, *f, a; int *idf, idfc, *idt; // check arguments if (TYPE(shape_to) != T_ARRAY){ rb_raise(rb_eTypeError, "1st arg must be an array"); } if (TYPE(idxmap) != T_ARRAY){ rb_raise(rb_eTypeError, "2nd arg must be an array"); } chk = rb_obj_is_kind_of(val_from, cNArray); if (chk == Qfalse) { rb_raise(rb_eTypeError, "3rd arg must be an NArray"); } // read argument (shape_to) rankt = RARRAY_LEN(shape_to); sht = ALLOCA_N(int, rankt); for(i=0; ishape; pf = NA_PTR_TYPE(val_from, double *); // read argument (missval) nomiss = (missval == Qnil); if (!nomiss){ vmiss = NUM2DBL(missval); } else { vmiss = -999.0; // dummy to avoid compiler warning (not used) } extr = (extrapo != Qfalse); // false -> 0(false); else -> true // read argument (idxmap) if (RARRAY_LEN(idxmap) != rankf){ rb_raise(rb_eArgError, "length of 2nd arg and rank of 3rd arg must agree"); } mtyp = ALLOCA_N(int, rankf); dm = ALLOCA_N(size_t, rankf); dm2 = ALLOCA_N(size_t, rankf); dm2f = ALLOCA_N(size_t, rankf); dm3 = ALLOCA_N(size_t, rankf); dm3f = ALLOCA_N(size_t, rankf); dm4 = ALLOCA_N(size_t, rankf); dm4f = ALLOCA_N(size_t, rankf); di = ALLOCA_N(int *, rankf); df = ALLOCA_N(double *, rankf); nid = 0; for(i=0; i 2**nid // prepare output object val_to = na_make_object(NA_DFLOAT, rankt, sht, cNArray); // double for a momnent lent = NA_TOTAL(val_to); pt = NA_PTR_TYPE(val_to, double *); // do interpolation idt = ALLOCA_N(int, rankt); idf = ALLOCA_N(int, rankf); for(it=0; it>k)%2 ? a*f[k] : a*(1.0 - f[k]) ); } cshf=1; kf = 0; k = 0; for(j=0; j0){ if ( (l>>k)%2 && idfc= 0 ){ break; } } if (i to be extrapolated if ( (P[j]-p[0])*(p[0]-p[n-1]) >= 0 ){ ids[j] = i = 0; } else { ids[j] = i = n-2; } } else { ids[j] = -999999; // a negative value i = 0; } f[j] = (p[i]-P[j])/(p[i]-p[i+1]); // second or later time finding : start from the previous position for(j=1; j= 0 ) { break; } else { if ( il>0 && ( down || ir==n-2 ) ){ il--; i = il; down = 0; // false } else if ( ir= 0 ){ i = 0; } else { i = n-2; } } else { i = -999999; // a negative value (changed to 0 below) } break; } } } ids[j] = i; if(i<0){i = 0; down = 0;} f[j] = (p[i]-P[j])/(p[i]-p[i+1]); } } static VALUE interpo_find_loc_1D(obj, X, x, missval, extrapo) VALUE obj; VALUE X; // [NArray(1D)] coordinate values onto which interpolation is made VALUE x; // [NArray(1D)] coordinate values of original data VALUE missval; // [Float] missing value in x VALUE extrapo; // [false/true] whether to extrapolate { VALUE na_ids, na_f; VALUE chk; size_t N, n; struct NARRAY *na; double *P, *p, vmiss; int extr; int *ids; double *f; int shape[1]; // could be size_t if NArray is changed // check and unwrap the input arguments chk = rb_obj_is_kind_of(X, cNArray); if (chk == Qfalse) {rb_raise(rb_eTypeError, "expect NArray (1st arg)");} chk = rb_obj_is_kind_of(x, cNArray); if (chk == Qfalse) {rb_raise(rb_eTypeError, "expect NArray (2nd arg)");} X = na_cast_object(X, NA_DFLOAT); GetNArray(X, na); N = na->total; P = (double *)NA_PTR(na, 0); x = na_cast_object(x, NA_DFLOAT); GetNArray(x, na); n = na->total; p = (double *)NA_PTR(na, 0); vmiss = NUM2DBL(missval); extr = (extrapo != Qfalse); // false -> 0(false); else -> true // prepare output NArrays shape[0] = N; na_ids = na_make_object(NA_LINT, 1, shape, cNArray); GetNArray(na_ids, na); ids = (int *) NA_PTR(na, 0); na_f = na_make_object(NA_DFLOAT, 1, shape, cNArray); GetNArray(na_f, na); f = (double *) NA_PTR(na, 0); // Do the job __interpo_find_loc_1D(N, P, n, p, vmiss, extr, ids, f); // Return return rb_ary_new3(2, na_ids, na_f); } /* To apply interpo_find_loc_1D multi-dimensionally */ static VALUE interpo_find_loc_1D_MD(obj, X, x, dimc, missval, extrapo) VALUE obj; VALUE X; // [NArray(1D)] coordinate values onto which interpolation is made VALUE x; // [NArray(multi-D)] coordinate values of original data VALUE dimc; // [Integer] the dimension in x except which mapping has been set VALUE missval; // [Float] missing value in x VALUE extrapo; // [false/true] whether to extrapolate { VALUE na_ids, na_f; VALUE chk; size_t N, n1; struct NARRAY *na; double *P, *p, *p1, vmiss; int extr; int *ids, *ids1; double *f, *f1; int *shr; // shape of the result (could be size_t if NArray is changed) int *shl; // shape of multi-D loop (could be size_t if NArray is changed) int *shx; // shape of x (could be size_t if NArray is changed) int dmc; // dimc int rank, dl, dc; size_t *cshxl, *cshrl, *cshl; // cumulative shapes for looping size_t fxl; // same but only for the dimension treated here size_t il, i, j, ix, ir, totl; // check and unwrap the input arguments chk = rb_obj_is_kind_of(X, cNArray); if (chk == Qfalse) {rb_raise(rb_eTypeError, "expect NArray (1st arg)");} chk = rb_obj_is_kind_of(x, cNArray); if (chk == Qfalse) {rb_raise(rb_eTypeError, "expect NArray (2nd arg)");} X = na_cast_object(X, NA_DFLOAT); GetNArray(X, na); N = na->total; P = (double *)NA_PTR(na, 0); dmc = NUM2INT( dimc ); vmiss = NUM2DBL(missval); extr = (extrapo != Qfalse); // false -> 0(false); else -> true x = na_cast_object(x, NA_DFLOAT); GetNArray(x, na); p = (double *)NA_PTR(na, 0); shx = na->shape; n1 = shx[dmc]; rank = NA_RANK(x); if (dmc<0 || dmc>=rank){ rb_raise(rb_eArgError, "Specified dimension (4th argument) is outside the dims of the multi-D coordinate variable"); } // prepare output NArrays shl = ALLOCA_N(int, rank-1); shr = ALLOCA_N(int, rank); shr[0] = N; totl = 1; for(dl=0,dc=0; dl