// // compute prefix sums of a grid // prefix_sums *compute_psums(grid *g) { // allocate structure prefix_sums *p = (prefix_sums *) ALLOC(prefix_sums); p->gridref = g; // allocate memory for prefix sums int size = g->width * g->height; p->A = (cell *) ALLOCV(cell,size); p->B = (cell *) ALLOCV(cell,size); p->X = (cell *) ALLOCV(cell,size); p->Y = (cell *) ALLOCV(cell,size); // fill in computation compute_sumA(p); compute_sumB(p); compute_sumX(p); compute_sumY(p); // check whether results are correct assert (check_sumA(p) && "computation of prefix A failed"); assert (check_sumB(p) && "computation of prefix B failed"); assert (check_sumX(p) && "computation of prefix X failed"); assert (check_sumY(p) && "computation of prefix Y failed"); return p; }
// // naive implementation of LRT // // the complexity of the naive implementation is O(n^6) and // hence not practical for larger grids. // // Steps: // 1. allocate memory for resulting rectangles and their scores // 2. compute grid totals // 2. compute lrt for each rectangle // 2.a) compute rectangle total // 2.b) compute score // 3. sort all rectangles according to their score // rectangle *naive_lrt(grid *g,int kbest) { int idx=0; // output index int i,j; // index for regions in grid // set width and height int width=g->width; int height=g->height; // compute number of rectangles in the grid and allocate // memory to store result size_t size = (size_t)(width + 1) * (size_t)width * (size_t)(height + 1) * (size_t)height / 4; rectangle *r = (rectangle *) ALLOCV(rectangle,size); // compute grid totals, ratio, and likelihood int g_n = 0; int g_k = 0; for (i=0; i<height; i++) { for (j=0; j<width; j++) { g_n += g->cells[I(i,j)].n; g_k += g->cells[I(i,j)].k; } } float g_q = (float)g_k / (float)g_n; float g_l = g_k * log(g_q); // compute LRT for all rectangle in grid int j1,i1,j2,i2; // coordinates of a rectangle for (i1=0; i1<height; i1++) { for (j1=0; j1<width; j1++) { for (i2=i1; i2<height; i2++) { for (j2=j1; j2<width; j2++) { // set rectangle width and height int r_width = j2 - j1 + 1; int r_height = i2 - i1 + 1; // compute rectangle totals, ratio and likelihood int r_n=0; int r_k=0; cell *c = &g->cells[i1*width+j1]; for (i=0; i<r_height; i++) { for (j=0; j<r_width; j++) { r_n += c[I(i,j)].n; r_k += c[I(i,j)].k; } } float r_q = (float)r_k / (float)r_n; float r_l = r_k * log(r_q) - r_k; // compute rectangle's complement totals, ratio, and likelihood int c_n = g_n - r_n; int c_k = g_k - r_k; float c_q = (float)c_k / (float)c_n; float c_l = c_k * log(c_q) - c_k; // compute score float score = r_l + c_l - g_l; // store result in array r r[idx].score = score; r[idx].i1 = i1; r[idx].j1 = j1; r[idx].i2 = i2; r[idx].j2 = j2; idx = idx + 1; } } } } // sort result and return it qsort(r,size,sizeof(rectangle),rectangle_compare); return r; }
// // fast implementation of LRT using prefix sums // rectangle *fast_lrt(grid *g,int kbest) { // heap size (initialized with zero and grows up to kbest) int heap_size=0; // set width and height int width = g->width; int height = g->height; // allocate heap with size k rectangle *r = (rectangle *) ALLOCV(rectangle,kbest); // compute prefix sums prefix_sums *p = compute_psums(g); // compute grid totals, ratio, and likelihood int g_n = p->A[width * height - 1].n; int g_k = p->A[width * height - 1].k; float g_q = (float)g_k / (float)g_n; float g_l = g_k * log(g_q); // compute LRT for each rectangle int j1,i1,j2,i2; // coordinates of a rectangle for (i1=0;i1<height;i1++){ for (j1=0;j1<width;j1++){ for (i2=i1;i2<height;i2++){ for (j2=j1;j2<width;j2++){ // compute rectangle totals, ratio and likelihood int a_n = p->A[I(i2,j2)].n; int a_k = p->A[I(i2,j2)].k; int b_n = p->B[I(i1,j1)].n; int b_k = p->B[I(i1,j1)].k; int y_n = p->Y[I(i1,j2)].n; int y_k = p->Y[I(i1,j2)].k; int x_n = p->X[I(i2,j1)].n; int x_k = p->X[I(i2,j1)].k; int r_n = a_n + b_n + x_n + y_n - g_n; int r_k = a_k + b_k + x_k + y_k - g_k; float r_q = (float)r_k / (float)r_n; float r_l = r_k * log(r_q) - r_k; // check whether prefix sums are correct #if DEBUG_LEVEL > 0 int t_n=0; int t_k=0; int i,j; int r_width = j2 - j1 + 1; int r_height = i2 - i1 + 1; cell *c = &g->cells[i1*width+j1]; for (i=0;i<r_height;i++) { for (j=0;j<r_width;j++) { t_n += c[I(i,j)].n; t_k += c[I(i,j)].k; } } assert((t_n == r_n && t_k == r_k) && "problems with prefix"); #endif // compute rectangle's complement totals, ratio, and likelihood int c_n = g_n - r_n; int c_k = g_k - r_k; float c_q = (float)c_k / (float)c_n; float c_l = c_k * log(c_q) - c_k; // compute score float score = r_l + c_l - g_l; // populate current rectangle rectangle current; current.score = score; current.i1 = i1; current.j1 = j1; current.i2 = i2; current.j2 = j2; // store result in heap // if the heap size is still smaller than kbest, add rectangle to the end of the heap // and rise the last element until the heap condition holds if (heap_size < kbest) { r[heap_size].score = score; r[heap_size].j1 = j1; r[heap_size].i1 = i1; r[heap_size].j2 = j2; r[heap_size].i2 = i2; heap_size = heap_size + 1; minheap_rise(r,heap_size,sizeof(rectangle),heap_rcmp); // otherwise check whether the current score is greater than the smallest element (=first element) // if so, replace the first element with current rectangle and sink the current element until // the heap condition holds. } else if (heap_rcmp(¤t,r) > 0) { r[0] = current; minheap_sink(r,kbest,sizeof(rectangle),heap_rcmp); } } } } } // sort result and return it qsort(r,kbest,sizeof(rectangle),rectangle_compare); return r; }
static VALUE function_call(int argc, VALUE argv[], VALUE self) { struct nogvl_ffi_call_args args = { 0 }; fiddle_generic *generic_args; VALUE cfunc, types, cPointer; int i; VALUE alloc_buffer = 0; cfunc = rb_iv_get(self, "@ptr"); types = rb_iv_get(self, "@args"); cPointer = rb_const_get(mFiddle, rb_intern("Pointer")); Check_Max_Args("number of arguments", argc); if (argc != (i = RARRAY_LENINT(types))) { rb_error_arity(argc, i, i); } TypedData_Get_Struct(self, ffi_cif, &function_data_type, args.cif); if (rb_safe_level() >= 1) { for (i = 0; i < argc; i++) { VALUE src = argv[i]; if (OBJ_TAINTED(src)) { rb_raise(rb_eSecurityError, "tainted parameter not allowed"); } } } generic_args = ALLOCV(alloc_buffer, (size_t)(argc + 1) * sizeof(void *) + (size_t)argc * sizeof(fiddle_generic)); args.values = (void **)((char *)generic_args + (size_t)argc * sizeof(fiddle_generic)); for (i = 0; i < argc; i++) { VALUE type = RARRAY_AREF(types, i); VALUE src = argv[i]; int argtype = FIX2INT(type); if (argtype == TYPE_VOIDP) { if(NIL_P(src)) { src = INT2FIX(0); } else if(cPointer != CLASS_OF(src)) { src = rb_funcall(cPointer, rb_intern("[]"), 1, src); } src = rb_Integer(src); } VALUE2GENERIC(argtype, src, &generic_args[i]); args.values[i] = (void *)&generic_args[i]; } args.values[argc] = NULL; args.fn = NUM2PTR(cfunc); (void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0); rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno)); #if defined(_WIN32) rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno)); #endif ALLOCV_END(alloc_buffer); return GENERIC2VALUE(rb_iv_get(self, "@return_type"), args.retval); }