Пример #1
0
/*
 * Set Handle Features
 */
int nvmed_handle_feature_set(NVMED_HANDLE* nvmed_handle, int feature, int value) {
	switch(feature) {
		case HANDLE_DIRECT_IO:
			if(value)
				FLAG_SET(nvmed_handle, HANDLE_DIRECT_IO);
			else
				FLAG_UNSET(nvmed_handle, HANDLE_DIRECT_IO);
			break;

		case HANDLE_SYNC_IO:
			if(value)
				FLAG_SET(nvmed_handle, HANDLE_SYNC_IO);
			else
				FLAG_UNSET(nvmed_handle, HANDLE_SYNC_IO);
			break;

		case HANDLE_HINT_DMEM:
			if(value)
				FLAG_SET(nvmed_handle, HANDLE_HINT_DMEM);
			else
				FLAG_UNSET(nvmed_handle, HANDLE_HINT_DMEM);
			break;
	}

	return value;
}
Пример #2
0
void HardwareIdList::removeItem(sarch_t id)
{
	uarch_t		rwFlags;
	sarch_t		maxIndex;

	arr.lock.readAcquire(&rwFlags);
	maxIndex = arr.rsrc.maxIndex;
	arr.lock.readRelease(rwFlags);

	if (id > maxIndex) {
		return;
	};

	arr.lock.writeAcquire();

	// If removing first item:
	if (arr.rsrc.firstValidIndex == id)
	{
		arr.rsrc.firstValidIndex = arr.rsrc.arr[id].next;
		// If is also last item, don't forget to update maxIndex.
		if (id == arr.rsrc.maxIndex) {
			arr.rsrc.maxIndex = HWIDLIST_INDEX_INVALID;
		};

		FLAG_UNSET(
			arr.rsrc.arr[id].flags, HWIDLIST_FLAGS_INDEX_VALID);

		arr.lock.writeRelease();
		return;
	};
	for (sarch_t i=arr.rsrc.firstValidIndex;
		i != HWIDLIST_INDEX_INVALID;
		i = arr.rsrc.arr[i].next)
	{
		if (arr.rsrc.arr[i].next == id)
		{
			if (id == arr.rsrc.maxIndex) {
				arr.rsrc.maxIndex = i;
			};

			arr.rsrc.arr[i].next = arr.rsrc.arr[id].next;
			FLAG_UNSET(
				arr.rsrc.arr[id].flags,
				HWIDLIST_FLAGS_INDEX_VALID);

			arr.lock.writeRelease();
			return;
		};
	};

	arr.lock.writeRelease();
}
Пример #3
0
void
clientInitFocusFlag (Client * c)
{
    ScreenInfo *screen_info;
    Client *c2;
    GList *list;
    guint workspace;

    g_return_if_fail (c != NULL);
    TRACE ("client \"%s\" (0x%lx)", c->name, c->window);

    if (!clientAcceptFocus (c) || (c->type & WINDOW_TYPE_DONT_FOCUS))
    {
       return;
    }

    screen_info = c->screen_info;
    workspace = c->win_workspace;
    for (list = screen_info->windows_stack; list; list = g_list_next (list))
    {
        c2 = (Client *) list->data;
        if ((c2->win_workspace == workspace) && FLAG_TEST (c2->xfwm_flags, XFWM_FLAG_FOCUS))
        {
            FLAG_UNSET (c2->xfwm_flags, XFWM_FLAG_FOCUS);
        }
    }
    FLAG_SET (c->xfwm_flags, XFWM_FLAG_FOCUS);
}
Пример #4
0
int esys_release(struct esys* esys, ocn_entity_token_t token)
{
    if(token >= OCN_MAX_ENTITIES)
        return OCN_ENTITY_ERR_RANGE;

    pthread_spin_lock(&esys->lock);

    struct entityslot* slot = &esys->slots[token];

    if(!FLAG_GET(slot->flags, ENTITYSLOT_FLAG_USED))
    {
        pthread_spin_unlock(&esys->lock);
        return OCN_ENTITY_ERR_NONEXIST;
    }

    if(!FLAG_GET(slot->flags, ENTITYSLOT_FLAG_ISOLATED))
    {
        pthread_spin_unlock(&esys->lock);
        return OCN_ENTITY_ERR_ISOLATED;
    }

    /* --- */

    FLAG_UNSET(slot->flags, ENTITYSLOT_FLAG_ISOLATED);

    /* --- */

    pthread_spin_unlock(&esys->lock);

    return OCN_OK;
}
Пример #5
0
void
clientUpdateFocus (ScreenInfo *screen_info, Client * c, unsigned short flags)
{
    Client *c2;
    gboolean restacked;

    TRACE ("entering");

    c2 = ((client_focus != c) ? client_focus : NULL);
    if ((c) && !clientAcceptFocus (c))
    {
        TRACE ("SKIP_FOCUS set for client \"%s\" (0x%lx)", c->name, c->window);
        pending_focus = NULL;
        return;
    }

    if ((c) && (c == client_focus) && !(flags & FOCUS_FORCE))
    {
        TRACE ("client \"%s\" (0x%lx) is already focused, ignoring request", c->name, c->window);
        pending_focus = NULL;
        return;
    }

    client_focus = c;
    if (c2)
    {
        clientSetNetState (c2);
        clientAdjustFullscreenLayer (c2, FALSE);
        frameQueueDraw (c2, FALSE);
        clientUpdateOpacity (c2);
    }
    if (c)
    {
        user_focus = c;
        clientInstallColormaps (c);
        if (flags & FOCUS_SORT)
        {
            clientSortRing(c);
        }
        if (FLAG_TEST(c->flags, CLIENT_FLAG_DEMANDS_ATTENTION))
        {
            TRACE ("un-setting WM_STATE_DEMANDS_ATTENTION flag on \"%s\" (0x%lx)", c->name, c->window);
            FLAG_UNSET (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION);
        }
        clientSetNetState (c);
        restacked = clientAdjustFullscreenLayer (c, TRUE);

        if (!restacked && screen_info->params->click_to_focus)
        {
            clientRaise (c, None);
            clientSetLastRaise (c);
        }
        frameQueueDraw (c, FALSE);
        clientUpdateOpacity (c);
    }
    clientSetNetActiveWindow (screen_info, c, 0);
    pending_focus = NULL;
}
Пример #6
0
int		loop_hook(t_env *e)
{
	if (FLAG_GET(e->flag, MASK_RECALC))
	{
		recalc_scene(e);
		ft_post_processing(e);
		ft_printelapsed(e);
		FLAG_UNSET(e->flag, MASK_RECALC);
	}
	mlx_put_image_to_window(e->mlx, e->win, e->screen->img, 0, 0);
	return (0);
}
Пример #7
0
void I8254Pit::disable(void)
{
	ubit16		disableDelayClks=1000;

	/**	EXPLANATION:
	 * 1. Program the i8254 to stop interrupting.
	 * 2. Unregister our ISR from Interrupt Trib.
	 *	InterruptTrib will automatically mask the IRQ pin off if
	 *	it determines that there are no more devices actively signaling
	 *	on the pin.
	 *
	 * Linux sets the i8254 to mode 0 (i.e, "oneshot"), with a 0 CLK pulse
	 * timeout when it wants to disable it. On two laptops from HP that I
	 * own, this approach generates a spurious IRQ.
	 *
	 * My own approach is to set the chip to mode 0 as well, but with a
	 * non-zero timeout (1000 CLKs {approx 1ms} specifically), forcing it
	 * to generate one last IRQ, and when that IRQ has come in, the device
	 * is effectively "disabled", in the sense that it was a oneshot
	 * timeout, so no more IRQs will be generated.
	 **/

	state.lock.acquire();
	if (i8254State.smpModeSwitchInProgress) { disableDelayClks = 50000; };

	// Write out the oneshot mode (mode 0) control byte.
	io::write8(
		i8254_CHAN0_IO_CONTROL,
		i8254_CHAN0_CONTROL_SELECT_COUNTER
		| i8254_CHAN0_CONTROL_MODE0_ONESHOT
		| i8254_CHAN0_CONTROL_COUNTER_WRITE_LOWHIGH);

	atomicAsm::memoryBarrier();
	io::write8(i8254_CHAN0_IO_COUNTER, disableDelayClks & 0xFF);
	io::write8(i8254_CHAN0_IO_COUNTER, disableDelayClks >> 8);
	FLAG_UNSET(
		state.rsrc.flags,
		ZKCM_TIMERDEV_STATE_FLAGS_ENABLED
		| ZKCM_TIMERDEV_STATE_FLAGS_SOFT_ENABLED);

	i8254State.irqState = sI8254State::DISABLING;

	state.lock.release();
	// We unregister the ISR, etc in the ISR when the final IRQ comes in.
}
Пример #8
0
error_t ibmPc_rtc_initialize(void)
{
	error_t		ret;
	ubit8		status1;

	ret = ibmPc_rtccmos_initialize();
	if (ret != ERROR_SUCCESS) { return ret; };

	rtccmos::lock();

	rtccmos::writeAddressRegister(RTC_REG_STATUS1);
	status1 = rtccmos::readDataRegister();
	// Clear all IRQs.
	FLAG_UNSET(status1,
		RTC_STATUS1_FLAGS_PERIODIC_IRQ_ENABLED
		| RTC_STATUS1_FLAGS_ALARM_IRQ_ENABLED
		| RTC_STATUS1_FLAGS_UPDATEEND_IRQ_ENABLED);

	rtccmos::writeAddressRegister(RTC_REG_STATUS1);
	rtccmos::writeDataRegister(status1);
	rtccmos::resetAddressRegister();

	rtccmos::unlock();


	rtccmos24HourTime =
		FLAG_TEST(status1, RTC_STATUS1_FLAGS_TIME_FORMAT_24HRS);

	if (!rtccmos24HourTime) {
		printf(ERROR RTCCMOS"Chip reports 12 hour format time.\n");
	};

	rtccmosBcdDateTime =
		!FLAG_TEST(status1, RTC_STATUS1_FLAGS_DATETIME_FORMAT_BIN);

	if (!rtccmosBcdDateTime)
	{
		printf(WARNING RTCCMOS"Date/Time is not in BCD. Possibly "
			"unstable or non-compliant chip.\n");
	};

	return ERROR_SUCCESS;
}
Пример #9
0
void
clientSetFocus (ScreenInfo *screen_info, Client *c, guint32 timestamp, unsigned short flags)
{
    Client *c2;

    TRACE ("entering");

    c2 = NULL;
    if ((c) && !(flags & FOCUS_IGNORE_MODAL))
    {
        c2 = clientGetModalFor (c);

        if (c2)
        {
            c = c2;
        }
    }
    c2 = ((client_focus != c) ? client_focus : NULL);
    if ((c) && FLAG_TEST (c->xfwm_flags, XFWM_FLAG_VISIBLE))
    {
        TRACE ("setting focus to client \"%s\" (0x%lx) with timestamp %u", c->name, c->window, (unsigned int) timestamp);
        user_focus = c;
        if (FLAG_TEST(c->flags, CLIENT_FLAG_DEMANDS_ATTENTION))
        {
            TRACE ("un-setting WM_STATE_DEMANDS_ATTENTION flag on \"%s\" (0x%lx)", c->name, c->window);
            FLAG_UNSET (c->flags, CLIENT_FLAG_DEMANDS_ATTENTION);
            clientSetNetState (c);
        }
        if ((c == client_focus) && !(flags & FOCUS_FORCE))
        {
            TRACE ("client \"%s\" (0x%lx) is already focused, ignoring request", c->name, c->window);
            return;
        }
        if (!clientAcceptFocus (c))
        {
            TRACE ("SKIP_FOCUS set for client \"%s\" (0x%lx)", c->name, c->window);
            return;
        }
        if (FLAG_TEST (c->wm_flags, WM_FLAG_INPUT) || !(screen_info->params->focus_hint))
        {
            pending_focus = c;
            /*
             * When shaded, the client window is unmapped, so it can not be focused.
             * Instead, we focus the frame that is still mapped.
             */
            if (FLAG_TEST (c->flags, CLIENT_FLAG_SHADED))
            {
                XSetInputFocus (myScreenGetXDisplay (screen_info), c->frame, RevertToPointerRoot, timestamp);
            }
            else
            {
                XSetInputFocus (myScreenGetXDisplay (screen_info), c->window, RevertToPointerRoot, timestamp);
            }
        }
        else if (flags & FOCUS_TRANSITION)
        {
            /*
             * If we are relying only on the client application to take focus, we need to set the focus
             * explicitely on our own fallback window otherwise there is a race condition between the
             * application and the window manager. If the application does not take focus before the
             * the previously focused window is unmapped (when iconifying or closing for example), the focus
             * will be reverted to the root window and focus transition will fail.
             */
            clientFocusNone (screen_info, c2, timestamp);
        }

        if (FLAG_TEST(c->wm_flags, WM_FLAG_TAKEFOCUS))
        {
            pending_focus = c;
            sendClientMessage (c->screen_info, c->window, WM_TAKE_FOCUS, timestamp);
        }
    }
    else
    {
        TRACE ("setting focus to none");

        client_focus = NULL;
        clientFocusNone (screen_info, c2, timestamp);
        clientClearDelayedFocus ();
    }
}
Пример #10
0
static int check_reg_size(struct globals *globals, int minsize, int row, int col)
{
    int rown, coln, n;
    int neighbors[8][2];
    int this_id;
    int ngbr_id;
    LARGEINT reg_size;
    struct RB_TREE *visited;
    struct rc next, ngbr_rc;
    struct rclist rilist;
    int no_check;
    
    if (!(FLAG_GET(globals->candidate_flag, row, col)))
	return minsize;

    FLAG_UNSET(globals->candidate_flag, row, col);

    visited = rbtree_create(cmp_rc, sizeof(struct rc));
    ngbr_rc.row = row;
    ngbr_rc.col = col;
    rbtree_insert(visited, &ngbr_rc);

    /* get this ID */
    Segment_get(&globals->rid_seg, (void *) &this_id, row, col);

    /* breadth-first search */
    next.row = row;
    next.col = col;
    rclist_init(&rilist);
    reg_size = 1;

    do {
	globals->find_neighbors(next.row, next.col, neighbors);
	n = globals->nn - 1;
	do {
	    rown = neighbors[n][0];
	    coln = neighbors[n][1];
	    no_check = 0;
	    if (rown < globals->row_min || rown >= globals->row_max ||
		coln < globals->col_min || coln >= globals->col_max)
		no_check = 1;
	    if (!no_check && (FLAG_GET(globals->null_flag, rown, coln)))
		no_check = 1;

	    ngbr_rc.row = rown;
	    ngbr_rc.col = coln;

	    if (!no_check && !rbtree_find(visited, &ngbr_rc)) {
		rbtree_insert(visited, &ngbr_rc);

		/* get neighbour ID */
		Segment_get(&globals->rid_seg, (void *) &ngbr_id, rown, coln);
		/* same neighbour */
		if (ngbr_id == this_id) {
		    reg_size++;
		    rclist_add(&rilist, rown, coln);
		    FLAG_UNSET(globals->candidate_flag, rown, coln);
		}
	    }
	} while (n--);    /* end do loop - next neighbor */
    } while (rclist_drop(&rilist, &next));   /* while there are cells to check */

    rclist_destroy(&rilist);
    rbtree_destroy(visited);

    return reg_size;
}
Пример #11
0
static int find_best_neighbour(struct globals *globals, int row, int col,
                               int this_id, struct NB_TREE *nbtree,
			       int *reg_size, struct ngbr_stats **Rbest,
			       int *best_n_row, int *best_n_col)
{
    int rown, coln, n, count;
    int neighbors[8][2];
    struct rc next, ngbr_rc;
    struct rclist rilist;
    int no_check;
    int ngbr_id;
    struct RB_TREE *visited;
    struct ngbr_stats Ri, Rk, *Rfound;
    double sim, best_sim;
    int best_n_id;
    int have_Ri;

    Ri.mean = G_malloc(globals->datasize);
    Rk.mean = G_malloc(globals->datasize);

    nbtree_clear(nbtree);
    FLAG_UNSET(globals->candidate_flag, row, col);

    visited = rbtree_create(cmp_rc, sizeof(struct rc));
    ngbr_rc.row = row;
    ngbr_rc.col = col;
    rbtree_insert(visited, &ngbr_rc);

    /* breadth-first search */
    next.row = row;
    next.col = col;
    rclist_init(&rilist);
    count = 1;
    best_n_id = -1;
    best_sim = 2;
    
    do {
	have_Ri = 0;
	globals->find_neighbors(next.row, next.col, neighbors);
	n = globals->nn - 1;
	do {
	    rown = neighbors[n][0];
	    coln = neighbors[n][1];
	    no_check = 0;
	    if (rown < globals->row_min || rown >= globals->row_max ||
		coln < globals->col_min || coln >= globals->col_max)
		no_check = 1;
	    if (!no_check && (FLAG_GET(globals->null_flag, rown, coln)))
		no_check = 1;

	    ngbr_rc.row = rown;
	    ngbr_rc.col = coln;

	    if (!no_check && !rbtree_find(visited, &ngbr_rc)) {
		rbtree_insert(visited, &ngbr_rc);

		/* get neighbor ID */
		Segment_get(&globals->rid_seg, (void *) &ngbr_id, rown, coln);
		/* same neighbour */
		if (ngbr_id == this_id) {
		    count++;
		    rclist_add(&rilist, rown, coln);
		    FLAG_UNSET(globals->candidate_flag, rown, coln);
		}
		else { /* different neighbour */
		    /* compare to this cell next.row, next.col */
		    if (!have_Ri) {
			Segment_get(globals->bands_out, (void *) Ri.mean, next.row, next.col);
			have_Ri = 1;
		    }
		    Segment_get(globals->bands_out, (void *) Rk.mean, rown, coln);
		    sim = globals->calculate_similarity(&Ri, &Rk, globals);
		    if (best_sim > sim) {
			best_sim = sim;
			best_n_id = ngbr_id;
			*best_n_row = rown;
			*best_n_col = coln;
		    }

		    /* find in neighbor tree */
		    Rk.id = ngbr_id;
		    if ((Rfound = nbtree_find(nbtree, &Rk))) {
			Rfound->count++;
			if (*Rbest && (*Rbest)->count < Rfound->count)
			    *Rbest = Rfound;
		    }
		    else {
			Rk.count = 1;
			Rk.row = rown;
			Rk.col = coln;
			nbtree_insert(nbtree, &Rk);
			if (!(*Rbest))
			    *Rbest = nbtree_find(nbtree, &Rk);
		    }
		}
	    }
	} while (n--);    /* end do loop - next neighbor */
    } while (rclist_drop(&rilist, &next));   /* while there are cells to check */

    rclist_destroy(&rilist);
    rbtree_destroy(visited);
    G_free(Ri.mean);
    G_free(Rk.mean);
    
    *reg_size = count;

    return best_n_id;
}
Пример #12
0
void
workspaceSwitch (ScreenInfo *screen_info, gint new_ws, Client * c2, gboolean update_focus, guint32 timestamp)
{
    DisplayInfo *display_info;
    Client *c, *new_focus;
    Client *previous;
    GList *list;
    Window dr, window;
    gint rx, ry, wx, wy;
    unsigned int mask;

    g_return_if_fail (screen_info != NULL);

    TRACE ("entering workspaceSwitch");

    display_info = screen_info->display_info;
    if ((new_ws == (gint) screen_info->current_ws) && (screen_info->params->toggle_workspaces))
    {
        new_ws = (gint) screen_info->previous_ws;
    }

    if (new_ws == (gint) screen_info->current_ws)
    {
        return;
    }

    if (screen_info->params->wrap_cycle)
    {
        if (new_ws > (gint) screen_info->workspace_count - 1)
        {
            new_ws = 0;
        }
        if (new_ws < 0)
        {
            new_ws = (gint) screen_info->workspace_count - 1;
        }
    }
    else if ((new_ws > (gint) screen_info->workspace_count - 1) || (new_ws < 0))
    {
        return;
    }

    screen_info->previous_ws = screen_info->current_ws;
    screen_info->current_ws = new_ws;

    new_focus = NULL;
    previous  = NULL;
    c = clientGetFocus ();

    if (c2)
    {
        clientSetWorkspace (c2, new_ws, FALSE);
    }

    if (c)
    {
        if (c->type & WINDOW_REGULAR_FOCUSABLE)
        {
            previous = c;
        }
        if (c2 == c)
        {
            new_focus = c2;
        }
    }

    /* First pass: Show, from top to bottom */
    for (list = g_list_last(screen_info->windows_stack); list; list = g_list_previous (list))
    {
        c = (Client *) list->data;
        if (FLAG_TEST (c->flags, CLIENT_FLAG_STICKY))
        {
            clientSetWorkspace (c, new_ws, TRUE);
        }
        else if (new_ws == (gint) c->win_workspace)
        {
            if (!FLAG_TEST (c->flags, CLIENT_FLAG_ICONIFIED) && !FLAG_TEST (c->xfwm_flags, XFWM_FLAG_VISIBLE))
            {
                if (!clientIsTransientOrModal (c) || !clientTransientOrModalHasAncestor (c, new_ws))
                {
                    clientShow (c, FALSE);
                }
            }
        }
    }

    /* Second pass: Hide from bottom to top */
    for (list = screen_info->windows_stack; list; list = g_list_next (list))
    {
        c = (Client *) list->data;

        if (new_ws != (gint) c->win_workspace)
        {
            if (c == previous)
            {
                FLAG_SET (previous->xfwm_flags, XFWM_FLAG_FOCUS);
                clientSetFocus (screen_info, NULL, timestamp, FOCUS_IGNORE_MODAL);
            }
            if (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_VISIBLE) && !FLAG_TEST (c->flags, CLIENT_FLAG_STICKY))
            {
                if (!clientIsTransientOrModal (c) || !clientTransientOrModalHasAncestor (c, new_ws))
                {
                    clientWithdraw (c, new_ws, FALSE);
                }
            }
        }
    }

    /* Third pass: Check for focus, from top to bottom */
    for (list = g_list_last(screen_info->windows_stack); list; list = g_list_previous (list))
    {
        c = (Client *) list->data;

        if (FLAG_TEST (c->flags, CLIENT_FLAG_STICKY))
        {
            if ((!new_focus) && (c == previous) && clientSelectMask (c, NULL, 0, WINDOW_REGULAR_FOCUSABLE))
            {
                new_focus = c;
            }
            FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_FOCUS);
        }
        else if (new_ws == (gint) c->win_workspace)
        {
            if ((!new_focus) && FLAG_TEST (c->xfwm_flags, XFWM_FLAG_FOCUS))
            {
                new_focus = c;
            }
            FLAG_UNSET (c->xfwm_flags, XFWM_FLAG_FOCUS);
        }
    }

    setNetCurrentDesktop (display_info, screen_info->xroot, new_ws);
    if (!(screen_info->params->click_to_focus))
    {
        if (!(c2) && (XQueryPointer (myScreenGetXDisplay (screen_info), screen_info->xroot, &dr, &window, &rx, &ry, &wx, &wy, &mask)))
        {
            c = clientAtPosition (screen_info, rx, ry, NULL);
            if (c)
            {
                new_focus = c;
            }
        }
    }

    if (update_focus)
    {
        if (new_focus)
        {
            if ((screen_info->params->click_to_focus) && (screen_info->params->raise_on_click))
            {
                if (!(screen_info->params->raise_on_focus) && !clientIsTopMost (new_focus))
                {
                    clientRaise (new_focus, None);
                }
            }
            clientSetFocus (screen_info, new_focus, timestamp, FOCUS_SORT);
        }
        else
        {
            clientFocusTop (screen_info, WIN_LAYER_FULLSCREEN, timestamp);
        }
    }
}
Пример #13
0
int find_con(int r, int c, double *d1, double *d2, DCELL * con1, DCELL * con2)
{
    int ct, low_ct, node_ct;
    int rr, cc, dor, doc;
    double dd, shortest;
    DCELL value;

    G_set_d_null_value(con1, 1);
    G_set_d_null_value(con2, 1);
    *d1 = *d2 = 1.0;
    shortest = nrows * ncols;
    for (rr = minr; rr <= maxr; rr++) {
	for (cc = minc; cc <= maxc; cc++)
	    FLAG_UNSET(seen, rr, cc);
    }
    minr = nrows;
    minc = ncols;
    maxr = maxc = -1;
    FLAG_SET(seen, r, c);
    if (r < minr)
	minr = r;
    if (r > maxr)
	maxr = r;
    if (c < minc)
	minc = c;
    if (c > maxc)
	maxc = c;
    node_ct = 0;
    zero = addpts(zero, r, c, r, c, &node_ct);
    low_ct = 0;
    while (1) {
	ct = low_ct++;
	if (node_ct <= ct)
	    return 1;
	rr = zero[ct].r;
	cc = zero[ct].c;
	dor = ABS(rr - r);
	doc = ABS(cc - c);
	if (rr >= 0 && cc >= 0 && rr < nrows && cc < ncols
	    && zero[ct].d < shortest && !flag_get(mask, rr, cc)) {
	    dseg_get(&con, rr, cc, &value);
	    if (G_is_d_null_value(&value))
		zero = addpts(zero, r, c, rr, cc, &node_ct);
	    else if (G_is_d_null_value(con1)) {
		*con1 = value;
		*d1 = MIN(dor, doc) * 1.414 + ABS(dor - doc);
		shortest = *d1 * 2.0 * i_val_l_f;
	    }
	    else if (*con1 == value) {
		dd = MIN(dor, doc) * 1.414 + ABS(dor - doc);
		if (dd < *d1) {
		    *d1 = dd;
		    shortest = dd * 2.0 * i_val_l_f;
		}
	    }
	    else if (G_is_d_null_value(con2)) {
		*con2 = value;
		*d2 = MIN(dor, doc) * 1.414 + ABS(dor - doc);
		shortest = *d2;
	    }
	    else {
		dd = MIN(dor, doc) * 1.414 + ABS(dor - doc);
		shortest = MIN(shortest, dd);
	    }
	}
    }

    return 0;
}
Пример #14
0
int do_cum(void)
{
    int r, c, dr, dc;
    char asp_val, asp_val_down;
    char is_swale, this_flag_value, flag_value;
    DCELL value, valued;
    POINT point;
    int killer, threshold;
    int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
    int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
    WAT_ALT wa, wadown;

    G_message(_("SECTION 3: Accumulating Surface Flow with SFD."));

    if (bas_thres <= 0)
	threshold = 60;
    else
	threshold = bas_thres;
    for (killer = 0; killer < do_points; killer++) {
	G_percent(killer, do_points, 1);
	seg_get(&astar_pts, (char *)&point, 0, killer);
	r = point.r;
	c = point.c;
	bseg_get(&asp, &asp_val, r, c);
	if (asp_val) {
	    dr = r + asp_r[ABS(asp_val)];
	    dc = c + asp_c[ABS(asp_val)];
	}
	/* skip user-defined depressions */
	else
	    dr = dc = -1;

	bseg_get(&bitflags, &this_flag_value, r, c);
	FLAG_UNSET(this_flag_value, WORKEDFLAG);

	if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) {
	    /* TODO: do not distribute flow along edges, this causes artifacts */
	    seg_get(&watalt, (char *)&wa, r, c);
	    value = wa.wat;
	    is_swale = FLAG_GET(this_flag_value, SWALEFLAG);
	    if (fabs(value) >= threshold && !is_swale) {
		is_swale = 1;
		FLAG_SET(this_flag_value, SWALEFLAG);
	    }
	    seg_get(&watalt, (char *)&wadown, dr, dc);
	    valued = wadown.wat;
	    if (value > 0) {
		if (valued > 0)
		    valued += value;
		else
		    valued -= value;
	    }
	    else {
		if (valued < 0)
		    valued += value;
		else
		    valued = value - valued;
	    }
	    wadown.wat = valued;
	    seg_put(&watalt, (char *)&wadown, dr, dc);
	    /* update asp for depression */
	    if (is_swale || fabs(valued) >= threshold) {
		bseg_get(&bitflags, &flag_value, dr, dc);
		FLAG_SET(flag_value, SWALEFLAG);
		bseg_put(&bitflags, &flag_value, dr, dc);
		is_swale = 1;
	    }
	    else {
		if (er_flag && !is_swale && !FLAG_GET(this_flag_value, RUSLEBLOCKFLAG))
		    slope_length(r, c, dr, dc);
	    }
	}
	bseg_put(&bitflags, &this_flag_value, r, c);
    }
    G_percent(do_points, do_points, 1);	/* finish it */

    seg_close(&astar_pts);

    return 0;
}
Пример #15
0
int do_cum_mfd(void)
{
    int r, c, dr, dc;
    DCELL value, valued, *wat_nbr;
    POINT point;
    WAT_ALT wa;
    int killer, threshold;

    /* MFD */
    int mfd_cells, stream_cells, swale_cells, astar_not_set, is_null;
    double *dist_to_nbr, *weight, sum_weight, max_weight;
    int r_nbr, c_nbr, r_max, c_max, ct_dir, np_side, max_side;
    double dx, dy;
    CELL ele, *ele_nbr;
    char asp_val, asp_val_down;
    double prop, max_acc;
    int workedon, edge, is_swale, flat;
    char *flag_nbr, this_flag_value, flag_value;
    int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
    int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };

    G_message(_("SECTION 3: Accumulating Surface Flow with MFD."));
    G_debug(1, "MFD convergence factor set to %d.", c_fac);

    /* distances to neighbours */
    dist_to_nbr = (double *)G_malloc(sides * sizeof(double));
    weight = (double *)G_malloc(sides * sizeof(double));

    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
	/* get r, c (r_nbr, c_nbr) for neighbours */
	r_nbr = nextdr[ct_dir];
	c_nbr = nextdc[ct_dir];
	/* account for rare cases when ns_res != ew_res */
	dy = ABS(r_nbr) * window.ns_res;
	dx = ABS(c_nbr) * window.ew_res;
	if (ct_dir < 4)
	    dist_to_nbr[ct_dir] = dx + dy;
	else
	    dist_to_nbr[ct_dir] = sqrt(dx * dx + dy * dy);
    }

    flag_nbr = (char *)G_malloc(sides * sizeof(char));
    wat_nbr = (DCELL *)G_malloc(sides * sizeof(DCELL));
    ele_nbr = (CELL *)G_malloc(sides * sizeof(CELL));

    workedon = 0;

    if (bas_thres <= 0)
	threshold = 60;
    else
	threshold = bas_thres;

    for (killer = 0; killer < do_points; killer++) {
	G_percent(killer, do_points, 1);
	seg_get(&astar_pts, (char *)&point, 0, killer);
	r = point.r;
	c = point.c;
	bseg_get(&asp, &asp_val, r, c);
	if (asp_val) {
	    dr = r + asp_r[ABS(asp_val)];
	    dc = c + asp_c[ABS(asp_val)];
	}
	/* skip user-defined depressions */
	else
	    dr = dc = -1;

	/* WORKEDFLAG has been set during A* Search
	 * reversed meaning here: 0 = done, 1 = not yet done */
	bseg_get(&bitflags, &this_flag_value, r, c);
	FLAG_UNSET(this_flag_value, WORKEDFLAG);
	
	if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) {
	    r_max = dr;
	    c_max = dc;

	    seg_get(&watalt, (char *)&wa, r, c);
	    value = wa.wat;

	    /* get weights */
	    max_weight = 0;
	    sum_weight = 0;
	    np_side = -1;
	    mfd_cells = 0;
	    stream_cells = 0;
	    swale_cells = 0;
	    astar_not_set = 1;
	    ele = wa.ele;
	    is_null = 0;
	    edge = 0;
	    flat = 1;
	    /* this loop is needed to get the sum of weights */
	    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
		/* get r, c (r_nbr, c_nbr) for neighbours */
		r_nbr = r + nextdr[ct_dir];
		c_nbr = c + nextdc[ct_dir];
		weight[ct_dir] = -1;

		wat_nbr[ct_dir] = 0;
		ele_nbr[ct_dir] = 0;

		/* check if neighbour is within region */
		if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
		    c_nbr < ncols) {

		    if (dr == r_nbr && dc == c_nbr)
			np_side = ct_dir;

		    bseg_get(&bitflags, &flag_nbr[ct_dir], r_nbr, c_nbr);
		    seg_get(&watalt, (char *)&wa, r_nbr, c_nbr);
		    wat_nbr[ct_dir] = wa.wat;
		    ele_nbr[ct_dir] = wa.ele;

		    /* check for swale or stream cells */
		    is_swale = FLAG_GET(flag_nbr[ct_dir], SWALEFLAG);
		    if (is_swale)
			swale_cells++;
		    if ((ABS(wat_nbr[ct_dir]) + 0.5) >= threshold &&
		        ct_dir != np_side && ele_nbr[ct_dir] > ele)
			stream_cells++;

		    if (FLAG_GET(flag_nbr[ct_dir], WORKEDFLAG)) {

			if (ele_nbr[ct_dir] != ele)
			    flat = 0;

			edge = is_null = FLAG_GET(flag_nbr[ct_dir], NULLFLAG);
			if (!is_null && ele_nbr[ct_dir] <= ele) {
			    if (ele_nbr[ct_dir] < ele) {
				weight[ct_dir] =
				    mfd_pow(((ele -
					      ele_nbr[ct_dir]) / dist_to_nbr[ct_dir]),
					    c_fac);
			    }
			    if (ele_nbr[ct_dir] == ele) {
				weight[ct_dir] =
				    mfd_pow((0.5 / dist_to_nbr[ct_dir]),
					    c_fac);
			    }
			    sum_weight += weight[ct_dir];
			    mfd_cells++;

			    if (weight[ct_dir] > max_weight) {
				max_weight = weight[ct_dir];
			    }

			    if (dr == r_nbr && dc == c_nbr) {
				astar_not_set = 0;
			    }
			}
		    }
		}
		else
		    edge = 1;
		if (edge)
		    break;
	    }
	    /* do not continue streams along edges, this causes artifacts */
	    if (edge) {
		is_swale = FLAG_GET(this_flag_value, SWALEFLAG);
		if (is_swale && asp_val > 0) {
		    asp_val = -1 * drain[r - r_nbr + 1][c - c_nbr + 1];
		    bseg_put(&asp, &asp_val, r, c);
		}
		bseg_put(&bitflags, &this_flag_value, r, c);
		continue;
	    }

	    /* honour A * path 
	     * mfd_cells == 0: fine, SFD along A * path
	     * mfd_cells == 1 && astar_not_set == 0: fine, SFD along A * path
	     * mfd_cells > 0 && astar_not_set == 1: A * path not included, add to mfd_cells
	     */

	    /* MFD, A * path not included, add to mfd_cells */
	    if (mfd_cells > 0 && astar_not_set == 1) {
		mfd_cells++;
		sum_weight += max_weight;
		weight[np_side] = max_weight;
		max_side = np_side;
	    }

	    /* set flow accumulation for neighbours */
	    max_acc = -1;
	    max_side = np_side;

	    if (mfd_cells > 1) {
		prop = 0.0;
		for (ct_dir = 0; ct_dir < sides; ct_dir++) {
		    r_nbr = r + nextdr[ct_dir];
		    c_nbr = c + nextdc[ct_dir];

		    /* check if neighbour is within region */
		    if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
			c_nbr < ncols && weight[ct_dir] > -0.5) {

			if (FLAG_GET(flag_nbr[ct_dir], WORKEDFLAG)) {

			    weight[ct_dir] = weight[ct_dir] / sum_weight;
			    /* check everything adds up to 1.0 */
			    prop += weight[ct_dir];

			    if (value > 0) {
				if (wat_nbr[ct_dir] > 0)
				    wat_nbr[ct_dir] += value * weight[ct_dir];
				else
				    wat_nbr[ct_dir] -= value * weight[ct_dir];
			    }
			    else {
				if (wat_nbr[ct_dir] < 0)
				    wat_nbr[ct_dir] += value * weight[ct_dir];
				else
				    wat_nbr[ct_dir] = value * weight[ct_dir] - wat_nbr[ct_dir];
			    }
			    valued = wat_nbr[ct_dir];
			    wa.wat = valued;
			    wa.ele = ele_nbr[ct_dir];
			    seg_put(&watalt, (char *)&wa, r_nbr, c_nbr);

			    /* get main drainage direction */
			    if (ABS(wat_nbr[ct_dir]) >= max_acc) {
				max_acc = ABS(wat_nbr[ct_dir]);
				r_max = r_nbr;
				c_max = c_nbr;
				max_side = ct_dir;
			    }
			}
			else if (ct_dir == np_side) {
			    /* check for consistency with A * path */
			    workedon++;
			}
		    }
		}

		/* adjust main drainage direction to A* path if possible */
		/*if (fabs(wat_nbr[np_side]) >= max_acc) {
		    max_acc = fabs(wat_nbr[np_side]);
		    r_max = dr;
		    c_max = dc;
		} */

		if (ABS(prop - 1.0) > 5E-6f) {
		    G_warning(_("MFD: cumulative proportion of flow distribution not 1.0 but %f"),
			      prop);
		}
	    }
	    /* SFD-like accumulation */
	    else {
		valued = wat_nbr[np_side];
		if (value > 0) {
		    if (valued > 0)
			valued += value;
		    else
			valued -= value;
		}
		else {
		    if (valued < 0)
			valued += value;
		    else
			valued = value - valued;
		}
		wa.wat = valued;
		wa.ele = ele_nbr[np_side];
		seg_put(&watalt, (char *)&wa, dr, dc);
	    }

	    /* update asp */
	    if (dr != r_max || dc != c_max) {
		if (asp_val < 0) {
		    asp_val = -1 * drain[r - r_max + 1][c - c_max + 1];
		}
		else
		    asp_val = drain[r - r_max + 1][c - c_max + 1];
		    
		bseg_put(&asp, &asp_val, r, c);
	    }
	    is_swale = FLAG_GET(this_flag_value, SWALEFLAG);
	    /* start new stream */
	    value = ABS(value) + 0.5;
	    if (!is_swale && (int)value >= threshold && stream_cells < 1 &&
		swale_cells < 1 && !flat) {
		FLAG_SET(this_flag_value, SWALEFLAG);
		is_swale = 1;
	    }
	    /* continue stream */
	    if (is_swale) {
		flag_value = flag_nbr[max_side];
		FLAG_SET(flag_value, SWALEFLAG);
		bseg_put(&bitflags, &flag_value, r_max, c_max);
	    }
	    else {
		if (er_flag && !is_swale && !FLAG_GET(this_flag_value, RUSLEBLOCKFLAG))
		    slope_length(r, c, r_max, c_max);
	    }
	}
	bseg_put(&bitflags, &this_flag_value, r, c);
    }
    G_percent(do_points, do_points, 1);	/* finish it */
    
    if (workedon)
	G_warning(_("MFD: A * path already processed when distributing flow: %d of %d cells"),
		  workedon, do_points);

    seg_close(&astar_pts);
    
    G_free(dist_to_nbr);
    G_free(weight);
    G_free(wat_nbr);
    G_free(ele_nbr);
    G_free(flag_nbr);

    return 0;
}
Пример #16
0
int do_cum_mfd(void)
{
    int r, c, dr, dc;
    CELL is_swale;
    DCELL value, valued, tci_div, sum_contour, cell_size;
    int killer, threshold;

    /* MFD */
    int mfd_cells, stream_cells, swale_cells, astar_not_set, is_null;
    double *dist_to_nbr, *contour, *weight, sum_weight, max_weight;
    int r_nbr, c_nbr, r_max, c_max, ct_dir, np_side;
    CELL ele, ele_nbr, aspect, is_worked;
    double prop, max_val;
    int workedon, edge, flat;
    int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
    int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
    int this_index, down_index, nbr_index;
    
    G_message(_("SECTION 3a: Accumulating Surface Flow with MFD."));
    G_debug(1, "MFD convergence factor set to %d.", c_fac);

    /* distances to neighbours, weights, contour lengths */
    dist_to_nbr = (double *)G_malloc(sides * sizeof(double));
    weight = (double *)G_malloc(sides * sizeof(double));
    contour = (double *)G_malloc(sides * sizeof(double));
    
    cell_size = get_dist(dist_to_nbr, contour);

    flag_clear_all(worked);
    workedon = 0;

    if (bas_thres <= 0)
	threshold = 60;
    else
	threshold = bas_thres;

    for (killer = 1; killer <= do_points; killer++) {
	G_percent(killer, do_points, 1);
	this_index = astar_pts[killer];
	seg_index_rc(alt_seg, this_index, &r, &c);
	FLAG_SET(worked, r, c);
	aspect = asp[this_index];
	if (aspect) {
	    dr = r + asp_r[ABS(aspect)];
	    dc = c + asp_c[ABS(aspect)];
	}
	else
	    dr = dc = -1;
	if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) { /* if ((dr = astar_pts[killer].downr) > -1) { */
	    value = wat[this_index];
	    down_index = SEG_INDEX(wat_seg, dr, dc);

	    /* get weights */
	    max_weight = 0;
	    sum_weight = 0;
	    np_side = -1;
	    mfd_cells = 0;
	    astar_not_set = 1;
	    ele = alt[this_index];
	    is_null = 0;
	    edge = 0;
	    /* this loop is needed to get the sum of weights */
	    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
		/* get r, c (r_nbr, c_nbr) for neighbours */
		r_nbr = r + nextdr[ct_dir];
		c_nbr = c + nextdc[ct_dir];
		weight[ct_dir] = -1;

		if (dr == r_nbr && dc == c_nbr)
		    np_side = ct_dir;

		/* check that neighbour is within region */
		if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
		    c_nbr < ncols) {

		    nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr);

		    valued = wat[nbr_index];
		    ele_nbr = alt[nbr_index];

		    is_worked = FLAG_GET(worked, r_nbr, c_nbr);
		    if (is_worked == 0) {
			is_null = Rast_is_c_null_value(&ele_nbr);
			edge = is_null;
			if (!is_null && ele_nbr <= ele) {
			    if (ele_nbr < ele) {
				weight[ct_dir] =
				    mfd_pow(((ele -
					      ele_nbr) / dist_to_nbr[ct_dir]),
					    c_fac);
			    }
			    if (ele_nbr == ele) {
				weight[ct_dir] =
				    mfd_pow((0.5 / dist_to_nbr[ct_dir]),
					    c_fac);
			    }
			    sum_weight += weight[ct_dir];
			    mfd_cells++;

			    if (weight[ct_dir] > max_weight) {
				max_weight = weight[ct_dir];
			    }

			    if (dr == r_nbr && dc == c_nbr) {
				astar_not_set = 0;
			    }
			    if (value < 0 && valued > 0)
				wat[nbr_index] = -valued;
			}
		    }
		}
		else
		    edge = 1;
		if (edge)
		    break;
	    }
	    /* do not distribute flow along edges, this causes artifacts */
	    if (edge) {
		continue;
	    }

	    /* honour A * path 
	     * mfd_cells == 0: fine, SFD along A * path
	     * mfd_cells == 1 && astar_not_set == 0: fine, SFD along A * path
	     * mfd_cells > 0 && astar_not_set == 1: A * path not included, add to mfd_cells
	     */

	    /* MFD, A * path not included, add to mfd_cells */
	    if (mfd_cells > 0 && astar_not_set == 1) {
		mfd_cells++;
		sum_weight += max_weight;
		weight[np_side] = max_weight;
	    }

	    /* set flow accumulation for neighbours */
	    max_val = -1;
	    tci_div = sum_contour = 0.;

	    if (mfd_cells > 1) {
		prop = 0.0;
		for (ct_dir = 0; ct_dir < sides; ct_dir++) {
		    r_nbr = r + nextdr[ct_dir];
		    c_nbr = c + nextdc[ct_dir];

		    /* check that neighbour is within region */
		    if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
			c_nbr < ncols && weight[ct_dir] > -0.5) {
			is_worked = FLAG_GET(worked, r_nbr, c_nbr);
			if (is_worked == 0) {

			    nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr);

			    weight[ct_dir] = weight[ct_dir] / sum_weight;
			    /* check everything adds up to 1.0 */
			    prop += weight[ct_dir];

			    if (atanb_flag) {
				sum_contour += contour[ct_dir];
				tci_div += get_slope_tci(ele, alt[nbr_index],
				                         dist_to_nbr[ct_dir]) *
					   weight[ct_dir];
			    }

			    valued = wat[nbr_index];
			    if (value > 0) {
				if (valued > 0)
				    valued += value * weight[ct_dir];
				else
				    valued -= value * weight[ct_dir];
			    }
			    else {
				if (valued < 0)
				    valued += value * weight[ct_dir];
				else
				    valued = value * weight[ct_dir] - valued;
			    }
			    wat[nbr_index] = valued;
			}
			else if (ct_dir == np_side) {
			    /* check for consistency with A * path */
			    workedon++;
			}
		    }
		}
		if (ABS(prop - 1.0) > 5E-6f) {
		    G_warning(_("MFD: cumulative proportion of flow distribution not 1.0 but %f"),
			      prop);
		}
	    }
	    /* SFD-like accumulation */
	    else {
		valued = wat[down_index];
		if (value > 0) {
		    if (valued > 0)
			valued += value;
		    else
			valued -= value;
		}
		else {
		    if (valued < 0)
			valued += value;
		    else
			valued = value - valued;
		}
		wat[down_index] = valued;

		if (atanb_flag) {
		    sum_contour = contour[np_side];
		    tci_div = get_slope_tci(ele, alt[down_index],
				            dist_to_nbr[np_side]);
		}
	    }
	    /* topographic wetness index ln(a / tan(beta)) and
	     * stream power index a * tan(beta) */
	    if (atanb_flag) {
		sca[this_index] = fabs(wat[this_index]) *
		                  (cell_size / sum_contour);
		tanb[this_index] = tci_div;
	    }
	}
    }
    if (workedon)
	G_warning(n_("MFD: A * path already processed when distributing flow: %d of %d cell", 
        "MFD: A * path already processed when distributing flow: %d of %d cells", 
        do_points),
		  workedon, do_points);


    G_message(_("SECTION 3b: Adjusting drainage directions."));

    for (killer = 1; killer <= do_points; killer++) {
	G_percent(killer, do_points, 1);
	this_index = astar_pts[killer];
	seg_index_rc(alt_seg, this_index, &r, &c);
	FLAG_UNSET(worked, r, c);
	aspect = asp[this_index];
	if (aspect) {
	    dr = r + asp_r[ABS(aspect)];
	    dc = c + asp_c[ABS(aspect)];
	}
	else
	    dr = dc = -1;
	if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) { /* if ((dr = astar_pts[killer].downr) > -1) { */
	    value = wat[this_index];
	    down_index = SEG_INDEX(wat_seg, dr, dc);

	    r_max = dr;
	    c_max = dc;

	    /* get max flow accumulation */
	    max_val = -1;
	    stream_cells = 0;
	    swale_cells = 0;
	    ele = alt[this_index];
	    is_null = 0;
	    edge = 0;
	    flat = 1;

	    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
		/* get r, c (r_nbr, c_nbr) for neighbours */
		r_nbr = r + nextdr[ct_dir];
		c_nbr = c + nextdc[ct_dir];

		/* check that neighbour is within region */
		if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 &&
		    c_nbr < ncols) {

		    nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr);

		    /* check for swale or stream cells */
		    is_swale = FLAG_GET(swale, r_nbr, c_nbr);
		    if (is_swale)
			swale_cells++;
		    valued = wat[nbr_index];
		    ele_nbr = alt[nbr_index];
		    edge = Rast_is_c_null_value(&ele_nbr);
		    if ((ABS(valued) + 0.5) >= threshold  &&
		        ele_nbr > ele)
			stream_cells++;

		    is_worked = !(FLAG_GET(worked, r_nbr, c_nbr));
		    if (is_worked == 0) {
			if (ele_nbr != ele)
			    flat = 0;
			is_null = Rast_is_c_null_value(&ele_nbr);
			edge = is_null;
			if (!is_null && ABS(valued) > max_val) {
			    max_val = ABS(valued);
			    r_max = r_nbr;
			    c_max = c_nbr;
			}
		    }
		}
		else
		    edge = 1;
		if (edge)
		    break;
	    }
	    /* do not distribute flow along edges, this causes artifacts */
	    if (edge) {
		is_swale = FLAG_GET(swale, r, c);
		if (is_swale && aspect > 0) {
		    aspect = -1 * drain[r - r_nbr + 1][c - c_nbr + 1];
		    asp[this_index] = aspect;
		}
		continue;
	    }
	    
	    /* update asp */
	    if (dr != r_max || dc != c_max) {
		aspect = drain[r - r_max + 1][c - c_max + 1];
		if (asp[this_index] < 0)
		    aspect = -aspect;
		asp[this_index] = aspect;
	    }
	    is_swale = FLAG_GET(swale, r, c);
	    /* start new stream */
	    value = ABS(value) + 0.5;
	    if (!is_swale && (int)value >= threshold && stream_cells < 1 &&
		swale_cells < 1 && !flat) {
		FLAG_SET(swale, r, c);
		is_swale = 1;
	    }
	    /* continue stream */
	    if (is_swale) {
		FLAG_SET(swale, r_max, c_max);
	    }
	    else {
		if (er_flag && !is_swale)
		    slope_length(r, c, r_max, c_max);
	    }
	}
    }

    G_free(astar_pts);

    flag_destroy(worked);

    G_free(dist_to_nbr);
    G_free(weight);

    return 0;
}
Пример #17
0
void walkerPageRanger::remapNoInc(
	VaddrSpace *vaddrSpace,
	void *vaddr, paddr_t paddr, uarch_t nPages,
	ubit8 op, uarch_t __kflags
	)
{
	uarch_t		l0Start, l0Current, l0End;
	uarch_t		l1Start, l1Current, l1Limit, l1End;
	paddr_t		l0Entry, l1Entry;
#ifdef CONFIG_ARCH_x86_32_PAE
	uarch_t		l2Start, l2Current, l2Limit, l2End;
	paddr_t		l2Entry;
#endif
	uarch_t		archFlags, localFlush;

	if (nPages == 0) { return; };

	localFlush = FLAG_TEST(__kflags, PAGEATTRIB_LOCAL_FLUSH_ONLY);
	vaddr = reinterpret_cast<void *>(
		(uarch_t)vaddr & PAGING_BASE_MASK_HIGH );

	archFlags = walkerPageRanger::encodeFlags(__kflags);
	getLevelRanges(
		vaddr, nPages,
		&l0Start, &l0End,
		&l1Start, &l1End
#ifdef CONFIG_ARCH_x86_32_PAE
		,&l2Start, &l2End
#endif
	);

	// This is SRS BSNS. Lock off both address spaces.
	vaddrSpace->level0Accessor.lock.acquire();
	cpuTrib.getCurrentCpuStream()->taskStream.getCurrentThread()->parent
		->getVaddrSpaceStream()->vaddrSpace
		.level0Accessor.lock.acquire();

	l0Current = l0Start;
	for (; l0Current <= l0End; l0Current++)
	{
		l0Entry = vaddrSpace->level0Accessor.rsrc->entries[l0Current];
		*level1Modifier = l0Entry;
		tlbControl::flushSingleEntry((void *)level1Accessor);

		l1Current = ((l0Current == l0Start) ? l1Start : 0);
		l1Limit = ((l0Current == l0End)
			? l1End : (PAGING_L1_NENTRIES - 1));

		for (; l1Current <= l1Limit; l1Current++)
		{
#ifdef CONFIG_ARCH_x86_32_PAE
			l1Entry = level1Accessor->entries[l1Current];
			*level2Modifier = l1Entry;
			tlbControl::flushSingleEntry((void *)level2Accessor);

			l2Current = (((l0Current == l0Start)
				&& (l1Current == l1Start)) ? l2Start : 0);

			l2Limit = (((l0Current == l0End)
				&& (l1Current == l1End))
				? l2End : (PAGING_L2_NENTRIES - 1))

			for (; l2Current < l2Limit; l2Current++)
			{
				l2Entry = level2Accessor->entries[l2Current]
					& 0xFFF;

				level2Accessor->entries[l2Current] = 0;
				level2Accessor->entries[l2Current] |= l2Entry;

				switch (op)
				{
				case WPRANGER_OP_SET:
				{
					FLAG_SET(
						level2Accessor
							->entries[l2Current],
						archFlags);

					break;
				};
				case WPRANGER_OP_CLEAR:
				{
					FLAG_UNSET(
						level2Accessor
							->entries[l2Current],
						archFlags);

					break;
				};
				case WPRANGER_OP_SET_PRESENT:
				{
					FLAG_SET(
						level2Accessor
							->entries[l2Current],
						PAGING_L2_PRESENT);

					break;
				};
				case WPRANGER_OP_CLEAR_PRESENT:
				{
					FLAG_UNSET(
						level2Accessor
							->entries[l2Current],
						PAGING_L2_PRESENT);

					break;
				};
				case WPRANGER_OP_SET_WRITE:
				{
					FLAG_SET(
						level2Accessor
							->entries[l2Current],
						PAGING_L2_WRITE);

					break;
				};
				case WPRANGER_OP_CLEAR_WRITE:
				{
					FLAG_UNSET(
						level2Accessor
							->entries[l2Current],
						PAGING_L2_WRITE);

					break;
				};
				default: break;
				};

				level2Accessor->entries[l2Current] |= paddr;
			};
#else
			l1Entry = level1Accessor->entries[l1Current] & 0xFFF;
			level1Accessor->entries[l1Current] = 0;
			level1Accessor->entries[l1Current] |= l1Entry;

			switch (op)
			{
			case WPRANGER_OP_SET:
			{
				FLAG_SET(
					level1Accessor->entries[l1Current],
					archFlags);

				break;
			};
			case WPRANGER_OP_CLEAR:
			{
				FLAG_UNSET(
					level1Accessor->entries[l1Current],
					archFlags);

				break;
			};
			case WPRANGER_OP_SET_PRESENT:
			{
				FLAG_SET(
					level1Accessor
						->entries[l1Current],
					PAGING_L1_PRESENT);

				break;
			};
			case WPRANGER_OP_CLEAR_PRESENT:
			{
				FLAG_UNSET(
					level1Accessor
						->entries[l1Current],
					PAGING_L1_PRESENT);

				break;
			};
			case WPRANGER_OP_SET_WRITE:
			{
				FLAG_SET(
					level1Accessor
						->entries[l1Current],
					PAGING_L1_WRITE);

				break;
			};
			case WPRANGER_OP_CLEAR_WRITE:
			{
				FLAG_UNSET(
					level1Accessor
						->entries[l1Current],
					PAGING_L1_WRITE);

				break;
			};
			default:
				break;
			};

			level1Accessor->entries[l1Current] |= paddr;
#endif
		};
	};

#if __SCALING__ > SCALING_SMP
	if (localFlush) {
		tlbControl::flushEntryRange(vaddr, nPages);
	}
	else {
		tlbControl::smpFlushEntryRange(vaddr, nPages);
	};
#else
	tlbControl::flushEntryRange(vaddr, nPages);
#endif

	vaddrSpace->level0Accessor.lock.release();
	cpuTrib.getCurrentCpuStream()->taskStream.getCurrentThread()->parent
		->getVaddrSpaceStream()->vaddrSpace
		.level0Accessor.lock.release();

	/*	FIXME:
	 * Insert code here to propagate possible changes to the kernel
	 * address space into the other process address spaces.
	 **/

	// We make the assumption that this did not fail.
}
Пример #18
0
int do_astar(void)
{
    int r, c, r_nbr, c_nbr, ct_dir;
    GW_LARGE_INT first_cum, count;
    int nextdr[8] = { 1, -1, 0, 0, -1, 1, 1, -1 };
    int nextdc[8] = { 0, 0, -1, 1, 1, -1, 1, -1 };
    CELL ele_val, ele_up, ele_nbr[8];
    WAT_ALT wa;
    ASP_FLAG af;
    char is_in_list, is_worked;
    HEAP_PNT heap_p;
    /* sides
     * |7|1|4|
     * |2| |3|
     * |5|0|6|
     */
    int nbr_ew[8] = { 0, 1, 2, 3, 1, 0, 0, 1 };
    int nbr_ns[8] = { 0, 1, 2, 3, 3, 2, 3, 2 };
    double dx, dy, dist_to_nbr[8], ew_res, ns_res;
    double slope[8];
    struct Cell_head window;
    int skip_diag;

    count = 0;

    first_cum = n_points;

    G_message(_("A* Search..."));

    Rast_get_window(&window);

    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
	/* get r, c (r_nbr, c_nbr) for neighbours */
	r_nbr = nextdr[ct_dir];
	c_nbr = nextdc[ct_dir];
	/* account for rare cases when ns_res != ew_res */
	dy = abs(r_nbr) * window.ns_res;
	dx = abs(c_nbr) * window.ew_res;
	if (ct_dir < 4)
	    dist_to_nbr[ct_dir] = dx + dy;
	else
	    dist_to_nbr[ct_dir] = sqrt(dx * dx + dy * dy);
    }
    ew_res = window.ew_res;
    ns_res = window.ns_res;
    
    while (heap_size > 0) {
	G_percent(count++, n_points, 1);
	if (count > n_points)
	    G_fatal_error(_("%lld surplus points"),
	                  heap_size);

	if (heap_size > n_points)
	    G_fatal_error
		(_("Too many points in heap %lld, should be %lld"),
		 heap_size, n_points);

	heap_p = heap_drop();

	r = heap_p.pnt.r;
	c = heap_p.pnt.c;

	ele_val = heap_p.ele;

	for (ct_dir = 0; ct_dir < sides; ct_dir++) {
	    /* get r, c (r_nbr, c_nbr) for neighbours */
	    r_nbr = r + nextdr[ct_dir];
	    c_nbr = c + nextdc[ct_dir];
	    slope[ct_dir] = ele_nbr[ct_dir] = 0;
	    skip_diag = 0;

	    /* check that neighbour is within region */
	    if (r_nbr < 0 || r_nbr >= nrows || c_nbr < 0 || c_nbr >= ncols)
		continue;

	    seg_get(&aspflag, (char *)&af, r_nbr, c_nbr);
	    is_in_list = FLAG_GET(af.flag, INLISTFLAG);
	    is_worked = FLAG_GET(af.flag, WORKEDFLAG);
	    if (!is_worked) {
		seg_get(&watalt, (char *)&wa, r_nbr, c_nbr);
		ele_nbr[ct_dir] = wa.ele;
		slope[ct_dir] = get_slope(ele_val, ele_nbr[ct_dir],
			                  dist_to_nbr[ct_dir]);
	    }
	    /* avoid diagonal flow direction bias */
	    if (!is_in_list) {
		if (ct_dir > 3 && slope[ct_dir] > 0) {
		    if (slope[nbr_ew[ct_dir]] > 0) {
			/* slope to ew nbr > slope to center */
			if (slope[ct_dir] <
			    get_slope(ele_nbr[nbr_ew[ct_dir]],
				       ele_nbr[ct_dir], ew_res))
			    skip_diag = 1;
		    }
		    if (!skip_diag && slope[nbr_ns[ct_dir]] > 0) {
			/* slope to ns nbr > slope to center */
			if (slope[ct_dir] <
			    get_slope(ele_nbr[nbr_ns[ct_dir]],
				       ele_nbr[ct_dir], ns_res))
			    skip_diag = 1;
		    }
		}
	    }

	    if (!skip_diag) {
		if (is_in_list == 0) {
		    ele_up = ele_nbr[ct_dir];
		    af.asp = drain[r_nbr - r + 1][c_nbr - c + 1];
		    heap_add(r_nbr, c_nbr, ele_up);
		    FLAG_SET(af.flag, INLISTFLAG);
		    seg_put(&aspflag, (char *)&af, r_nbr, c_nbr);
		}
		else if (is_in_list && is_worked == 0) {
		    if (FLAG_GET(af.flag, EDGEFLAG)) {
			/* neighbour is edge in list, not yet worked */
			if (af.asp < 0) {
			    /* adjust flow direction for edge cell */
			    af.asp = drain[r_nbr - r + 1][c_nbr - c + 1];
			    seg_put(&aspflag, (char *)&af, r_nbr, c_nbr);
			}
		    }
		    else if (FLAG_GET(af.flag, DEPRFLAG)) {
			G_debug(3, "real depression");
			/* neighbour is inside real depression, not yet worked */
			if (af.asp == 0 && ele_val <= ele_nbr[ct_dir]) {
			    af.asp = drain[r_nbr - r + 1][c_nbr - c + 1];
			    FLAG_UNSET(af.flag, DEPRFLAG);
			    seg_put(&aspflag, (char *)&af, r_nbr, c_nbr);
			}
		    }
		}
	    }
	}    /* end neighbours */
	/* add astar points to sorted list for flow accumulation and stream extraction */
	first_cum--;
	seg_put(&astar_pts, (char *)&heap_p.pnt, 0, first_cum);
	seg_get(&aspflag, (char *)&af, r, c);
	FLAG_SET(af.flag, WORKEDFLAG);
	seg_put(&aspflag, (char *)&af, r, c);
    }    /* end A* search */

    G_percent(n_points, n_points, 1);	/* finish it */

    return 1;
}
Пример #19
0
int thin_seg(int stream_id)
{
    int thinned = 0;
    int r, c, r_nbr, c_nbr, last_r, last_c;
    CELL curr_stream, no_stream = 0;
    int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 };
    int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 };
    ASP_FLAG af;

    r = stream_node[stream_id].r;
    c = stream_node[stream_id].c;

    cseg_get(&stream, &curr_stream, r, c);

    seg_get(&aspflag, (char *)&af, r, c);
    if (af.asp > 0) {
	/* get downstream point */
	last_r = r + asp_r[(int)af.asp];
	last_c = c + asp_c[(int)af.asp];
	cseg_get(&stream, &curr_stream, last_r, last_c);

	if (curr_stream != stream_id)
	    return thinned;

	/* get next downstream point */
	seg_get(&aspflag, (char *)&af, last_r, last_c);
	while (af.asp > 0) {
	    r_nbr = last_r + asp_r[(int)af.asp];
	    c_nbr = last_c + asp_c[(int)af.asp];

	    if (r_nbr == last_r && c_nbr == last_c)
		return thinned;
	    if (r_nbr < 0 || r_nbr >= nrows || c_nbr < 0 || c_nbr >= ncols)
		return thinned;
	    cseg_get(&stream, &curr_stream, r_nbr, c_nbr);
	    if (curr_stream != stream_id)
		return thinned;
	    if (abs(r_nbr - r) < 2 && abs(c_nbr - c) < 2) {
		/* eliminate last point */
		cseg_put(&stream, &no_stream, last_r, last_c);
		FLAG_UNSET(af.flag, STREAMFLAG);
		seg_put(&aspflag, (char *)&af, last_r, last_c);
		/* update start point */
		seg_get(&aspflag, (char *)&af, r, c);
		af.asp = drain[r - r_nbr + 1][c - c_nbr + 1];
		seg_put(&aspflag, (char *)&af, r, c);

		thinned = 1;
	    }
	    else {
		/* nothing to eliminate, continue from last point */
		r = last_r;
		c = last_c;
	    }
	    last_r = r_nbr;
	    last_c = c_nbr;
	    seg_get(&aspflag, (char *)&af, last_r, last_c);
	}
    }

    return thinned;
}
Пример #20
0
status_t I8254Pit::isr(ZkcmDeviceBase *self, ubit32 flags)
{
	(void)		flags;
	ubit32		devFlags;
	sZkcmTimerEvent	*irqEvent;
	I8254Pit	*device;
	error_t		err;
	modeE		mode;

	/**	EXPLANATION:
	 * 1. Check to make sure that this is not a "disabling" IRQ which is
	 *    meant to cause the i8254 to stop sending in IRQs. If it is the
	 *    disabling IRQ, unregister the ISR and exit.
	 * 2. If this is not a disabling IRQ, queue an event and exit.
	 **/
	device = static_cast<I8254Pit *>( self );

	device->state.lock.acquire();

	devFlags = device->state.rsrc.flags;
	mode = device->state.rsrc.mode;

	// If this is the "disabling" final cleanup IRQ:
	if (device->i8254State.irqState == sI8254State::DISABLING)
	{
		device->i8254State.isrRegistered = 0;
		device->i8254State.irqState = sI8254State::DISABLED;

		device->state.lock.release();

		// Part of the IBM-PC Symmetric IO mode switch.
		if (device->i8254State.smpModeSwitchInProgress)
		{
			// Release the lock and exit.
			taskTrib.unblock(
				device->i8254State.smpModeSwitchThread);
		};

		return ZKCM_ISR_SUCCESS_AND_RETIRE_ME;
	};

	// Small state machine cleanup for oneshot mode: unset the ENABLED flag.
	if (mode == ONESHOT)
	{
		FLAG_UNSET(
			device->state.rsrc.flags,
			ZKCM_TIMERDEV_STATE_FLAGS_ENABLED
			| ZKCM_TIMERDEV_STATE_FLAGS_SOFT_ENABLED);
	};

	device->state.lock.release();

	// Don't claim the IRQ if the timer hadn't been enabled.
	if (!FLAG_TEST(devFlags, ZKCM_TIMERDEV_STATE_FLAGS_ENABLED)) {
		return ZKCM_ISR_NOT_MY_IRQ;
	};

	device->sendEoi();

	// Invoke the system clock update routine if installed on this device.
	if (device->clockRoutine != NULL)
	{
		// Accesses state without the lock. Safe.
		(*device->clockRoutine)(
			(mode == ONESHOT)
				? device->state.rsrc.currentTimeout.nseconds
				: device->state.rsrc.currentInterval.nseconds);
	};

	// Create an event.
	if (!FLAG_TEST(devFlags, ZKCM_TIMERDEV_STATE_FLAGS_SOFT_ENABLED)) {
		return ZKCM_ISR_SUCCESS;
	};

	irqEvent = device->allocateIrqEvent();
	// Note well, this is faultable memory being allocated.
	if (irqEvent == NULL)
	{
		printf(WARNING i8254"isr: Couldn't allocate IRQ event.\n");
		// FIXME: I don't like this return value.
		return ZKCM_ISR_SUCCESS;
	};

	// Fill out the event and queue it.
	irqEvent->device = device;
	device->getLatchState(
		&irqEvent->latchedStream);

	timerTrib.getCurrentDateTime(&irqEvent->irqStamp);
	err = device->irqEventQueue.addItem(irqEvent);
	if (err != ERROR_SUCCESS)
	{
		device->freeIrqEvent(irqEvent);
		printf(WARNING i8254"isr: Failed to queue IRQ event; "
			"err %s.\n",
			strerror(err));
	};

	return ZKCM_ISR_SUCCESS;
}
Пример #21
0
int create_isegs(struct globals *globals)
{
    int row, col;
    int successflag = 1;
    int have_bound, rid;
    CELL current_bound, bounds_val;

    if (globals->bounds_map == NULL) {
	/* just one time through loop */
	successflag = globals->method_fn(globals);
    }
    else {
	/* outer processing loop for polygon constraints */
	for (current_bound = globals->lower_bound;
	     current_bound <= globals->upper_bound; current_bound++) {

	    G_debug(1, "current_bound = %d", current_bound);

	    have_bound = 0;

	    /* get min/max row/col to narrow the processing window */
	    globals->row_min = globals->nrows;
	    globals->row_max = 0;
	    globals->col_min = globals->ncols;
	    globals->col_max = 0;
	    for (row = 0; row < globals->nrows; row++) {
		for (col = 0; col < globals->ncols; col++) {
		    FLAG_SET(globals->null_flag, row, col);
		    Segment_get(&globals->bounds_seg, &bounds_val,
				row, col);

		    if (!Rast_is_c_null_value(&bounds_val)
		        && bounds_val == current_bound) {

			Segment_get(&globals->rid_seg, &rid, row, col);
			if (!Rast_is_c_null_value(&rid)) {
			    have_bound = 1;

			    FLAG_UNSET(globals->null_flag, row, col);

			    if (globals->row_min > row)
				globals->row_min = row;
			    if (globals->row_max < row)
				globals->row_max = row;
			    if (globals->col_min > col)
				globals->col_min = col;
			    if (globals->col_max < col)
				globals->col_max = col;
			}
		    }
		}
	    }
	    globals->row_max++;
	    globals->col_max++;

	    if (have_bound)
		successflag = globals->method_fn(globals);
	}    /* end outer loop for processing polygons */

	/* restore NULL flag */
	flag_clear_all(globals->null_flag);
	for (row = 0; row < globals->nrows; row++) {
	    for (col = 0; col < globals->ncols; col++) {
		Segment_get(&globals->rid_seg, &rid, row, col);
		if (Rast_is_c_null_value(&rid))
		    FLAG_SET(globals->null_flag, row, col);
	    }
	}
    }

    return successflag;
}
Пример #22
0
void Indep(void)
{
    int Count, DRow, DCol;
    int Found, R, C;
    double RowDist, RowDistSq, ColDist;
    struct History history;

    G_debug(2, "indep()");

    Count = 0;
    Found = 0;

    while (CellCount > 0) {
	G_debug(3, "(CellCount):%d", CellCount);
	G_debug(3, "(Count):%d", Count);

	DRow = DoNext[Count].R;
	DCol = DoNext[Count++].C;

	if (0 != FlagGet(Cells, DRow, DCol)) {
	    /* FLAG_SET( Out, DRow, DCol); */
	    Out[DRow][DCol] = ++Found;
	    for (R = DRow; R < Rs; R++) {
		RowDist = NS * (R - DRow);
		if (RowDist > MaxDistSq) {
		    R = Rs;
		}
		else {
		    RowDistSq = RowDist * RowDist;
		    for (C = DCol; C < Cs; C++) {
			ColDist = EW * (C - DCol);
			G_debug(3, "(RowDistSq):%.12lf", RowDistSq);
			G_debug(3, "(ColDist):%.12lf", ColDist);
			G_debug(3, "(MaxDistSq):%.12lf", MaxDistSq);
			
			if (MaxDistSq >= RowDistSq + ColDist * ColDist) {
			    if (0 != FlagGet(Cells, R, C)) {
				G_debug(2, "unset()");
				FLAG_UNSET(Cells, R, C);
				CellCount--;
			    }
			}
			else {
			    C = Cs;
			}
		    }
		}
	    }

	    G_debug(2, "it1()");
	    for (R = DRow - 1; R >= 0; R--) {
		RowDist = NS * (DRow - R);
		if (RowDist > MaxDistSq) {
		    R = 0;
		}
		else {
		    RowDistSq = RowDist * RowDist;
		    for (C = DCol; C < Cs; C++) {
			ColDist = EW * (C - DCol);
			if (MaxDistSq >= RowDistSq + ColDist * ColDist) {
			    if (0 != FlagGet(Cells, R, C)) {
				G_debug(2, "unset()");
				FLAG_UNSET(Cells, R, C);
				CellCount--;
			    }
			}
			else {
			    C = Cs;
			}
		    }
		}
	    }

	    G_debug(2, "it2()");
	    for (R = DRow; R < Rs; R++) {
		RowDist = NS * (R - DRow);
		if (RowDist > MaxDistSq) {
		    R = Rs;
		}
		else {
		    RowDistSq = RowDist * RowDist;
		    for (C = DCol - 1; C >= 0; C--) {
			ColDist = EW * (DCol - C);
			if (MaxDistSq >= RowDistSq + ColDist * ColDist) {
			    if (0 != FlagGet(Cells, R, C)) {
				G_debug(2, "unset()");
				FLAG_UNSET(Cells, R, C);
				CellCount--;
			    }
			}
			else {
			    C = 0;
			}
		    }
		}
	    }

	    G_debug(2, "it3()");
	    for (R = DRow - 1; R >= 0; R--) {
		RowDist = NS * (DRow - R);
		if (RowDist > MaxDistSq) {
		    R = 0;
		}
		else {
		    RowDistSq = RowDist * RowDist;
		    for (C = DCol - 1; C >= 0; C--) {
			ColDist = EW * (DCol - C);
			if (MaxDistSq >= RowDistSq + ColDist * ColDist) {
			    if (0 != FlagGet(Cells, R, C)) {
				G_debug(2, "unset()");
				FLAG_UNSET(Cells, R, C);
				CellCount--;
			    }
			}
			else {
			    C = 0;
			}
		    }
		}
	    }
	}
    }

    G_debug(2, "outputting()");
    OutFD = Rast_open_c_new(Output->answer);

    G_message(_("Writing raster map <%s>..."),
	      Output->answer);
    for (R = 0; R < Rs; R++) {
	G_percent(R, Rs, 2);
	for (C = 0; C < Cs; C++) {
	    CellBuffer[C] = Out[R][C];
	}
	Rast_put_row(OutFD, CellBuffer, CELL_TYPE);
    }
    G_percent(1, 1, 1);
    
    Rast_close(OutFD);
    Rast_short_history(Output->answer, "raster", &history);
    Rast_command_history(&history);
    Rast_write_history(Output->answer, &history);
}