Example #1
0
/* ---------- OpenWGroup -----------------------------------------------*/
IFFP OpenWGroup(GroupContext *parent0,GroupContext* new0)
{
	register GroupContext *parent = parent0;
	register GroupContext *newtmp    = new0;
	register int ckEnd;
	register IFFP iffp = IFF_OKAY;

	newtmp->parent       = parent;
	newtmp->clientFrame  = parent->clientFrame;
	newtmp->file         = parent->file;
	newtmp->position     = parent->position;
	newtmp->bound        = parent->bound;
	newtmp->ckHdr.ckID   = NULL_CHUNK;
	newtmp->ckHdr.ckSize = newtmp->bytesSoFar = 0;

	if ( Known(parent->ckHdr.ckSize) ) {
		ckEnd = newtmp->position + ChunkMoreBytes(parent);
		if ( newtmp->bound == szNotYetKnown || newtmp->bound > ckEnd )
			newtmp->bound = ckEnd;
	};

	if ( parent->ckHdr.ckID == NULL_CHUNK || /* not currently writing a chunk*/
		IS_ODD(newtmp->position) ||
		(Known(newtmp->bound) && IS_ODD(newtmp->bound)) )
		iffp = CLIENT_ERROR;
	return(iffp);
}
Example #2
0
/* ---------- PutCkEnd -------------------------------------------------*/
IFFP PutCkEnd(GroupContext *context0)
{
	register GroupContext *context = context0;
	WORD zero = 0;   /* padding source */

	if ( context->ckHdr.ckID == NULL_CHUNK )  /* not in a chunk */
		return(CLIENT_ERROR);

	if ( context->ckHdr.ckSize == szNotYetKnown ) {
		/* go back and set the chunk size to bytesSoFar */
		int offset = context->bytesSoFar+sizeof(int);
		if ( 0 > GSeek(context->file,
			-(offset),
			OFFSET_CURRENT))
		{
			return(DOS_ERROR);
		} else
		{
			context->bytesSoFar = endianSwap32(context->bytesSoFar);
			if (0 > fwrite(&context->bytesSoFar, 1,sizeof(int),context->file))
				return (DOS_ERROR);
			context->bytesSoFar = endianSwap32(context->bytesSoFar);
			if (0 > GSeek(context->file, context->bytesSoFar, OFFSET_CURRENT)  )
				return (DOS_ERROR);
		}


	}
	else {  /* make sure the client wrote as many bytes as planned */
		if ( context->ckHdr.ckSize != context->bytesSoFar )
			return(CLIENT_ERROR);
	};

	/* Write a pad byte if needed to bring us up to an even boundary.
	* Since the context end must be even, and since we haven't
	* overwritten the context, if we're on an odd position there must
	* be room for a pad byte. */
	if ( IS_ODD(context->bytesSoFar) ) {
		if ( 0 > fwrite(&zero, 1,1,context->file) )
			return(DOS_ERROR);
		context->position += 1;
	};

	context->ckHdr.ckID   = NULL_CHUNK;
	context->ckHdr.ckSize = context->bytesSoFar = 0;
	return(IFF_OKAY);
}
Example #3
0
// odd processes send/recv and even processes rcv/snd
void ring(double *outgoing, double *incoming, int buff_count, int num_procs, int num_shifts, int my_id) {
	int prev, next, i, tag = 3;
	MPI_Status status;

	next = (my_id + 1)%num_procs;
	prev = (my_id == 0)?(num_procs - 1):(my_id - 1);

	if(IS_ODD(my_id)) {
		for(i = 0; i < num_shifts; i ++) {
			MPI_Send(outgoing, buff_count, MPI_DOUBLE, next, tag, MPI_COMM_WORLD);
			MPI_Recv(incoming, buff_count, MPI_DOUBLE, prev, tag, MPI_COMM_WORLD, &status);
		}
	} else {
		for(i = 0; i < num_shifts; i ++) {
			MPI_Recv(incoming, buff_count, MPI_DOUBLE, prev, tag, MPI_COMM_WORLD, &status);
			MPI_Send(outgoing, buff_count, MPI_DOUBLE, next, tag, MPI_COMM_WORLD);
		}
	}
}
Example #4
0
IFFP OpenWIFF(BPTR file, GroupContext *new0, int limit)
{
	register GroupContext *newtmp = new0;
	register IFFP iffp = IFF_OKAY;

	newtmp->parent       = NULL;
	newtmp->clientFrame  = NULL;
	newtmp->file         = file;
	newtmp->position     = 0;
	newtmp->bound        = limit;
	newtmp->ckHdr.ckID   = NULL_CHUNK;  /* indicates no current chunk */
	newtmp->ckHdr.ckSize = newtmp->bytesSoFar = 0;

	if (0 > Seek(file, 0, OFFSET_BEGINNING))   /* Go to start of the file.*/
		iffp = DOS_ERROR;
	else if ( Known(limit) && IS_ODD(limit) )
		iffp = CLIENT_ERROR;
	return(iffp);
}
Example #5
0
/*
	Converts arcs added by 'add_edge()' calls
	to a forward star graph representation.

	Linear time algorithm.
	No or little additional memory is allocated
	during this process
	(it may be necessary to allocate additional
	arc blocks, since arcs corresponding to the
	same node must be contiguous, i.e. be in one
	arc block.)
*/
void Graph::prepare_graph()
{
	node *i;
	arc_for_block *ab_for, *ab_for_first;
	arc_rev_block *ab_rev, *ab_rev_first, *ab_rev_scan;
	arc_forward *a_for;
	arc_reverse *a_rev, *a_rev_scan, a_rev_tmp;
	node_block *nb;
	bool for_flag = false, rev_flag = false;
	int k;

	if (!arc_rev_block_first)
	{
		node_id from = add_node(), to = add_node();
		add_edge(from, to, 1, 0);
	}

	/* FIRST STAGE */
	a_rev_tmp.sister = NULL;
	for (a_rev=arc_rev_block_first->current; a_rev<&arc_rev_block_first->arcs_rev[ARC_BLOCK_SIZE]; a_rev++)
	{
		a_rev -> sister = NULL;
	}

	ab_for = ab_for_first = arc_for_block_first;
	ab_rev = ab_rev_first = ab_rev_scan = arc_rev_block_first;
	a_for = &ab_for->arcs_for[0];
	a_rev = a_rev_scan = &ab_rev->arcs_rev[0];

	for (nb=node_block_first; nb; nb=nb->next)
	{
		for (i=&nb->nodes[0]; i<nb->current; i++)
		{
			/* outgoing arcs */
			k = (int) i -> first_out;
			if (a_for + k > &ab_for->arcs_for[ARC_BLOCK_SIZE])
			{
				if (k > ARC_BLOCK_SIZE) { if (error_function) (*error_function)("# of arcs per node exceeds block size!"); exit(1); }
				if (for_flag) ab_for = NULL;
				else          { ab_for = ab_for -> next; ab_rev_scan = ab_rev_scan -> next; }
				if (ab_for == NULL)
				{
					arc_for_block *next = arc_for_block_first;
					char *ptr = new char[sizeof(arc_for_block)+1];
					if (!ptr) { if (error_function) (*error_function)("Not enough memory!"); exit(1); }
					if ((int)ptr & 1) arc_for_block_first = (arc_for_block *) (ptr + 1);
					else              arc_for_block_first = (arc_for_block *) ptr;
					arc_for_block_first -> start = ptr;
					arc_for_block_first -> current = & ( arc_for_block_first -> arcs_for[0] );
					arc_for_block_first -> next = next;
					ab_for = arc_for_block_first;
					for_flag = true;
				}
				else a_rev_scan = &ab_rev_scan->arcs_rev[0];
				a_for = &ab_for->arcs_for[0];
			}
			if (ab_rev_scan)
			{
				a_rev_scan += k;
				i -> parent = (arc_forward *) a_rev_scan;
			}
			else i -> parent = (arc_forward *) &a_rev_tmp;
			a_for += k;
			i -> first_out = a_for;
			ab_for -> last_node = i;

			/* incoming arcs */
			k = (int) i -> first_in;
			if (a_rev + k > &ab_rev->arcs_rev[ARC_BLOCK_SIZE])
			{
				if (k > ARC_BLOCK_SIZE) { if (error_function) (*error_function)("# of arcs per node exceeds block size!"); exit(1); }
				if (rev_flag) ab_rev = NULL;
				else          ab_rev = ab_rev -> next;
				if (ab_rev == NULL)
				{
					arc_rev_block *next = arc_rev_block_first;
					char *ptr = new char[sizeof(arc_rev_block)+1];
					if (!ptr) { if (error_function) (*error_function)("Not enough memory!"); exit(1); }
					if ((int)ptr & 1) arc_rev_block_first = (arc_rev_block *) (ptr + 1);
					else              arc_rev_block_first = (arc_rev_block *) ptr;
					arc_rev_block_first -> start = ptr;
					arc_rev_block_first -> current = & ( arc_rev_block_first -> arcs_rev[0] );
					arc_rev_block_first -> next = next;
					ab_rev = arc_rev_block_first;
					rev_flag = true;
				}
				a_rev = &ab_rev->arcs_rev[0];
			}
			a_rev += k;
			i -> first_in = a_rev;
			ab_rev -> last_node = i;
		}
		/* i is the last node in block */
		i -> first_out = a_for;
		i -> first_in  = a_rev;
	}

	/* SECOND STAGE */
	for (ab_for=arc_for_block_first; ab_for; ab_for=ab_for->next)
	{
		ab_for -> current = ab_for -> last_node -> first_out;
	}

	for ( ab_for=ab_for_first, ab_rev=ab_rev_first;
		  ab_for;
		  ab_for=ab_for->next, ab_rev=ab_rev->next )
	for ( a_for=&ab_for->arcs_for[0], a_rev=&ab_rev->arcs_rev[0];
		  a_for<&ab_for->arcs_for[ARC_BLOCK_SIZE];
		  a_for++, a_rev++ )
	{
		arc_forward *af;
		arc_reverse *ar;
		node *from;
		int shift = 0, shift_new;
		captype r_cap, r_rev_cap, r_cap_new, r_rev_cap_new;

		if (!(from=(node *)(a_rev->sister))) continue;
		af = a_for;
		ar = a_rev;

		do
		{
			ar -> sister = NULL;

			shift_new = ((char *)(af->shift)) - (char *)from;
			r_cap_new = af -> r_cap;
			r_rev_cap_new = af -> r_rev_cap;
			if (shift)
			{
				af -> shift = shift;
				af -> r_cap = r_cap;
				af -> r_rev_cap = r_rev_cap;
			}
			shift = shift_new;
			r_cap = r_cap_new;
			r_rev_cap = r_rev_cap_new;

			af = -- from -> first_out;
			if ((arc_reverse *)(from->parent) != &a_rev_tmp)
			{
				from -> parent = (arc_forward *)(((arc_reverse *)(from -> parent)) - 1);
				ar = (arc_reverse *)(from -> parent);
			}
		} while (from=(node *)(ar->sister));

		af -> shift = shift;
		af -> r_cap = r_cap;
		af -> r_rev_cap = r_rev_cap;
	}

	for (ab_for=arc_for_block_first; ab_for; ab_for=ab_for->next)
	{
		i = ab_for -> last_node;
		a_for = i -> first_out;
		ab_for -> current -> shift     = a_for -> shift;
		ab_for -> current -> r_cap     = a_for -> r_cap;
		ab_for -> current -> r_rev_cap = a_for -> r_rev_cap;
		a_for -> shift = (int) (ab_for -> current + 1);
		i -> first_out = (arc_forward *) (((char *)a_for) - 1);
	}

	/* THIRD STAGE */
	for (ab_rev=arc_rev_block_first; ab_rev; ab_rev=ab_rev->next)
	{
		ab_rev -> current = ab_rev -> last_node -> first_in;
	}

	for (nb=node_block_first; nb; nb=nb->next)
	for (i=&nb->nodes[0]; i<nb->current; i++)
	{
		arc_forward *a_for_first, *a_for_last;

		a_for_first = i -> first_out;
		if (IS_ODD(a_for_first))
		{
			a_for_first = (arc_forward *) (((char *)a_for_first) + 1);
			a_for_last = (arc_forward *) ((a_for_first ++) -> shift);
		}
		else a_for_last = (i + 1) -> first_out;

		for (a_for=a_for_first; a_for<a_for_last; a_for++)
		{
			node *to = NEIGHBOR_NODE(i, a_for -> shift);
			a_rev = -- to -> first_in;
			a_rev -> sister = a_for;
		}
	}

	for (ab_rev=arc_rev_block_first; ab_rev; ab_rev=ab_rev->next)
	{
		i = ab_rev -> last_node;
		a_rev = i -> first_in;
		ab_rev -> current -> sister = a_rev -> sister;
		a_rev -> sister = (arc_forward *) (ab_rev -> current + 1);
		i -> first_in = (arc_reverse *) (((char *)a_rev) - 1);
	}
}
Example #6
0
Graph::flowtype Graph::maxflow()
{
	node *i, *j, *current_node = NULL, *s_start, *t_start;
	captype *cap_middle, *rev_cap_middle;
	arc_forward *a_for, *a_for_first, *a_for_last;
	arc_reverse *a_rev, *a_rev_first, *a_rev_last;
	nodeptr *np, *np_next;

	prepare_graph();
	maxflow_init();
	nodeptr_block = new DBlock<nodeptr>(NODEPTR_BLOCK_SIZE, error_function);

	while ( 1 )
	{
		if (i=current_node)
		{
			i -> next = NULL; /* remove active flag */
			if (!i->parent) i = NULL;
		}
		if (!i)
		{
			if (!(i = next_active())) break;
		}

		/* growth */
		s_start = NULL;

		a_for_first = i -> first_out;
		if (IS_ODD(a_for_first))
		{
			a_for_first = (arc_forward *) (((char *)a_for_first) + 1);
			a_for_last = (arc_forward *) ((a_for_first ++) -> shift);
		}
		else a_for_last = (i + 1) -> first_out;
		a_rev_first = i -> first_in;
		if (IS_ODD(a_rev_first))
		{
			a_rev_first = (arc_reverse *) (((char *)a_rev_first) + 1);
			a_rev_last = (arc_reverse *) ((a_rev_first ++) -> sister);
		}
		else a_rev_last = (i + 1) -> first_in;

		if (!i->is_sink)
		{
			/* grow source tree */
			for (a_for=a_for_first; a_for<a_for_last; a_for++)
			if (a_for->r_cap)
			{
				j = NEIGHBOR_NODE(i, a_for -> shift);
				if (!j->parent)
				{
					j -> is_sink = 0;
					j -> parent = MAKE_ODD(a_for);
					j -> TS = i -> TS;
					j -> DIST = i -> DIST + 1;
					set_active(j);
				}
				else if (j->is_sink)
				{
					s_start = i;
					t_start = j;
					cap_middle     = & ( a_for -> r_cap );
					rev_cap_middle = & ( a_for -> r_rev_cap );
					break;
				}
				else if (j->TS <= i->TS &&
				         j->DIST > i->DIST)
				{
					/* heuristic - trying to make the distance from j to the source shorter */
					j -> parent = MAKE_ODD(a_for);
					j -> TS = i -> TS;
					j -> DIST = i -> DIST + 1;
				}
			}
			if (!s_start)
			for (a_rev=a_rev_first; a_rev<a_rev_last; a_rev++)
			{
				a_for = a_rev -> sister;
				if (a_for->r_rev_cap)
				{
					j = NEIGHBOR_NODE_REV(i, a_for -> shift);
					if (!j->parent)
					{
						j -> is_sink = 0;
						j -> parent = a_for;
						j -> TS = i -> TS;
						j -> DIST = i -> DIST + 1;
						set_active(j);
					}
					else if (j->is_sink)
					{
						s_start = i;
						t_start = j;
						cap_middle     = & ( a_for -> r_rev_cap );
						rev_cap_middle = & ( a_for -> r_cap );
						break;
					}
					else if (j->TS <= i->TS &&
							 j->DIST > i->DIST)
					{
						/* heuristic - trying to make the distance from j to the source shorter */
						j -> parent = a_for;
						j -> TS = i -> TS;
						j -> DIST = i -> DIST + 1;
					}
				}
			}
		}
		else
		{
			/* grow sink tree */
			for (a_for=a_for_first; a_for<a_for_last; a_for++)
			if (a_for->r_rev_cap)
			{
				j = NEIGHBOR_NODE(i, a_for -> shift);
				if (!j->parent)
				{
					j -> is_sink = 1;
					j -> parent = MAKE_ODD(a_for);
					j -> TS = i -> TS;
					j -> DIST = i -> DIST + 1;
					set_active(j);
				}
				else if (!j->is_sink)
				{
					s_start = j;
					t_start = i;
					cap_middle     = & ( a_for -> r_rev_cap );
					rev_cap_middle = & ( a_for -> r_cap );
					break;
				}
				else if (j->TS <= i->TS &&
				         j->DIST > i->DIST)
				{
					/* heuristic - trying to make the distance from j to the sink shorter */
					j -> parent = MAKE_ODD(a_for);
					j -> TS = i -> TS;
					j -> DIST = i -> DIST + 1;
				}
			}
			for (a_rev=a_rev_first; a_rev<a_rev_last; a_rev++)
			{
				a_for = a_rev -> sister;
				if (a_for->r_cap)
				{
					j = NEIGHBOR_NODE_REV(i, a_for -> shift);
					if (!j->parent)
					{
						j -> is_sink = 1;
						j -> parent = a_for;
						j -> TS = i -> TS;
						j -> DIST = i -> DIST + 1;
						set_active(j);
					}
					else if (!j->is_sink)
					{
						s_start = j;
						t_start = i;
						cap_middle     = & ( a_for -> r_cap );
						rev_cap_middle = & ( a_for -> r_rev_cap );
						break;
					}
					else if (j->TS <= i->TS &&
							 j->DIST > i->DIST)
					{
						/* heuristic - trying to make the distance from j to the sink shorter */
						j -> parent = a_for;
						j -> TS = i -> TS;
						j -> DIST = i -> DIST + 1;
					}
				}
			}
		}

		TIME ++;

		if (s_start)
		{
			i -> next = i; /* set active flag */
			current_node = i;

			/* augmentation */
			augment(s_start, t_start, cap_middle, rev_cap_middle);
			/* augmentation end */

			/* adoption */
			while (np=orphan_first)
			{
				np_next = np -> next;
				np -> next = NULL;

				while (np=orphan_first)
				{
					orphan_first = np -> next;
					i = np -> ptr;
					nodeptr_block -> Delete(np);
					if (!orphan_first) orphan_last = NULL;
					if (i->is_sink) process_sink_orphan(i);
					else            process_source_orphan(i);
				}

				orphan_first = np_next;
			}
			/* adoption end */
		}
		else current_node = NULL;
	}

	delete nodeptr_block;

	return flow;
}
Example #7
0
void Graph::process_sink_orphan(node *i)
{
	node *j;
	arc_forward *a0_for, *a0_for_first, *a0_for_last;
	arc_reverse *a0_rev, *a0_rev_first, *a0_rev_last;
	arc_forward *a0_min = NULL, *a;
	nodeptr *np;
	int d, d_min = INFINITE_D;

	/* trying to find a new parent */
	a0_for_first = i -> first_out;
	if (IS_ODD(a0_for_first))
	{
		a0_for_first = (arc_forward *) (((char *)a0_for_first) + 1);
		a0_for_last = (arc_forward *) ((a0_for_first ++) -> shift);
	}
	else a0_for_last = (i + 1) -> first_out;
	a0_rev_first = i -> first_in;
	if (IS_ODD(a0_rev_first))
	{
		a0_rev_first = (arc_reverse *) (((char *)a0_rev_first) + 1);
		a0_rev_last  = (arc_reverse *) ((a0_rev_first ++) -> sister);
	}
	else a0_rev_last = (i + 1) -> first_in;


	for (a0_for=a0_for_first; a0_for<a0_for_last; a0_for++)
	if (a0_for->r_cap)
	{
		j = NEIGHBOR_NODE(i, a0_for -> shift);
		if (j->is_sink && (a=j->parent))
		{
			/* checking the origin of j */
			d = 0;
			while ( 1 )
			{
				if (j->TS == TIME)
				{
					d += j -> DIST;
					break;
				}
				a = j -> parent;
				d ++;
				if (a==TERMINAL)
				{
					j -> TS = TIME;
					j -> DIST = 1;
					break;
				}
				if (a==ORPHAN) { d = INFINITE_D; break; }
				if (IS_ODD(a))
					j = NEIGHBOR_NODE_REV(j, MAKE_EVEN(a) -> shift);
				else
					j = NEIGHBOR_NODE(j, a -> shift);
			}
			if (d<INFINITE_D) /* j originates from the sink - done */
			{
				if (d<d_min)
				{
					a0_min = a0_for;
					d_min = d;
				}
				/* set marks along the path */
				for (j=NEIGHBOR_NODE(i, a0_for->shift); j->TS!=TIME; )
				{
					j -> TS = TIME;
					j -> DIST = d --;
					a = j->parent;
					if (IS_ODD(a))
						j = NEIGHBOR_NODE_REV(j, MAKE_EVEN(a) -> shift);
					else
						j = NEIGHBOR_NODE(j, a -> shift);
				}
			}
		}
	}
	for (a0_rev=a0_rev_first; a0_rev<a0_rev_last; a0_rev++)
	{
		a0_for = a0_rev -> sister;
		if (a0_for->r_rev_cap)
		{
			j = NEIGHBOR_NODE_REV(i, a0_for -> shift);
			if (j->is_sink && (a=j->parent))
			{
				/* checking the origin of j */
				d = 0;
				while ( 1 )
				{
					if (j->TS == TIME)
					{
						d += j -> DIST;
						break;
					}
					a = j -> parent;
					d ++;
					if (a==TERMINAL)
					{
						j -> TS = TIME;
						j -> DIST = 1;
						break;
					}
					if (a==ORPHAN) { d = INFINITE_D; break; }
					if (IS_ODD(a))
						j = NEIGHBOR_NODE_REV(j, MAKE_EVEN(a) -> shift);
					else
						j = NEIGHBOR_NODE(j, a -> shift);
				}
				if (d<INFINITE_D) /* j originates from the sink - done */
				{
					if (d<d_min)
					{
						a0_min = MAKE_ODD(a0_for);
						d_min = d;
					}
					/* set marks along the path */
					for (j=NEIGHBOR_NODE_REV(i,a0_for->shift); j->TS!=TIME; )
					{
						j -> TS = TIME;
						j -> DIST = d --;
						a = j->parent;
						if (IS_ODD(a))
							j = NEIGHBOR_NODE_REV(j, MAKE_EVEN(a) -> shift);
						else
							j = NEIGHBOR_NODE(j, a -> shift);
					}
				}
			}
		}
	}

	if (i->parent = a0_min)
	{
		i -> TS = TIME;
		i -> DIST = d_min + 1;
	}
	else
	{
		/* no parent is found */
		i -> TS = 0;

		/* process neighbors */
		for (a0_for=a0_for_first; a0_for<a0_for_last; a0_for++)
		{
			j = NEIGHBOR_NODE(i, a0_for -> shift);
			if (j->is_sink && (a=j->parent))
			{
				if (a0_for->r_cap) set_active(j);
				if (a!=TERMINAL && a!=ORPHAN && IS_ODD(a) && NEIGHBOR_NODE_REV(j, MAKE_EVEN(a)->shift)==i)
				{
					/* add j to the adoption list */
					j -> parent = ORPHAN;
					np = nodeptr_block -> New();
					np -> ptr = j;
					if (orphan_last) orphan_last -> next = np;
					else             orphan_first        = np;
					orphan_last = np;
					np -> next = NULL;
				}
			}
		}
		for (a0_rev=a0_rev_first; a0_rev<a0_rev_last; a0_rev++)
		{
			a0_for = a0_rev -> sister;
			j = NEIGHBOR_NODE_REV(i, a0_for -> shift);
			if (j->is_sink && (a=j->parent))
			{
				if (a0_for->r_rev_cap) set_active(j);
				if (a!=TERMINAL && a!=ORPHAN && !IS_ODD(a) && NEIGHBOR_NODE(j, a->shift)==i)
				{
					/* add j to the adoption list */
					j -> parent = ORPHAN;
					np = nodeptr_block -> New();
					np -> ptr = j;
					if (orphan_last) orphan_last -> next = np;
					else             orphan_first        = np;
					orphan_last = np;
					np -> next = NULL;
				}
			}
		}
	}
}
Example #8
0
void Graph::augment(node *s_start, node *t_start, captype *cap_middle, captype *rev_cap_middle)
{
	node *i;
	arc_forward *a;
	captype bottleneck;
	nodeptr *np;


	/* 1. Finding bottleneck capacity */
	/* 1a - the source tree */
	bottleneck = *cap_middle;
	for (i=s_start; ; )
	{
		a = i -> parent;
		if (a == TERMINAL) break;
		if (IS_ODD(a))
		{
			a = MAKE_EVEN(a);
			if (bottleneck > a->r_cap) bottleneck = a -> r_cap;
			i = NEIGHBOR_NODE_REV(i, a -> shift);
		}
		else
		{
			if (bottleneck > a->r_rev_cap) bottleneck = a -> r_rev_cap;
			i = NEIGHBOR_NODE(i, a -> shift);
		}
	}
	if (bottleneck > i->tr_cap) bottleneck = i -> tr_cap;
	/* 1b - the sink tree */
	for (i=t_start; ; )
	{
		a = i -> parent;
		if (a == TERMINAL) break;
		if (IS_ODD(a))
		{
			a = MAKE_EVEN(a);
			if (bottleneck > a->r_rev_cap) bottleneck = a -> r_rev_cap;
			i = NEIGHBOR_NODE_REV(i, a -> shift);
		}
		else
		{
			if (bottleneck > a->r_cap) bottleneck = a -> r_cap;
			i = NEIGHBOR_NODE(i, a -> shift);
		}
	}
	if (bottleneck > - i->tr_cap) bottleneck = - i -> tr_cap;


	/* 2. Augmenting */
	/* 2a - the source tree */
	*rev_cap_middle += bottleneck;
	*cap_middle -= bottleneck;
	for (i=s_start; ; )
	{
		a = i -> parent;
		if (a == TERMINAL) break;
		if (IS_ODD(a))
		{
			a = MAKE_EVEN(a);
			a -> r_rev_cap += bottleneck;
			a -> r_cap -= bottleneck;
			if (!a->r_cap)
			{
				/* add i to the adoption list */
				i -> parent = ORPHAN;
				np = nodeptr_block -> New();
				np -> ptr = i;
				np -> next = orphan_first;
				orphan_first = np;
			}
			i = NEIGHBOR_NODE_REV(i, a -> shift);
		}
		else
		{
			a -> r_cap += bottleneck;
			a -> r_rev_cap -= bottleneck;
			if (!a->r_rev_cap)
			{
				/* add i to the adoption list */
				i -> parent = ORPHAN;
				np = nodeptr_block -> New();
				np -> ptr = i;
				np -> next = orphan_first;
				orphan_first = np;
			}
			i = NEIGHBOR_NODE(i, a -> shift);
		}
	}
	i -> tr_cap -= bottleneck;
	if (!i->tr_cap)
	{
		/* add i to the adoption list */
		i -> parent = ORPHAN;
		np = nodeptr_block -> New();
		np -> ptr = i;
		np -> next = orphan_first;
		orphan_first = np;
	}
	/* 2b - the sink tree */
	for (i=t_start; ; )
	{
		a = i -> parent;
		if (a == TERMINAL) break;
		if (IS_ODD(a))
		{
			a = MAKE_EVEN(a);
			a -> r_cap += bottleneck;
			a -> r_rev_cap -= bottleneck;
			if (!a->r_rev_cap)
			{
				/* add i to the adoption list */
				i -> parent = ORPHAN;
				np = nodeptr_block -> New();
				np -> ptr = i;
				np -> next = orphan_first;
				orphan_first = np;
			}
			i = NEIGHBOR_NODE_REV(i, a -> shift);
		}
		else
		{
			a -> r_rev_cap += bottleneck;
			a -> r_cap -= bottleneck;
			if (!a->r_cap)
			{
				/* add i to the adoption list */
				i -> parent = ORPHAN;
				np = nodeptr_block -> New();
				np -> ptr = i;
				np -> next = orphan_first;
				orphan_first = np;
			}
			i = NEIGHBOR_NODE(i, a -> shift);
		}
	}
	i -> tr_cap += bottleneck;
	if (!i->tr_cap)
	{
		/* add i to the adoption list */
		i -> parent = ORPHAN;
		np = nodeptr_block -> New();
		np -> ptr = i;
		np -> next = orphan_first;
		orphan_first = np;
	}


	flow += bottleneck;
}