Ejemplo n.º 1
0
void reduce_pivots(MutableMatrix *M)
{
  int nr = M->n_rows()-1;
  int nc = M->n_cols()-1;
  if (nr < 0 || nc < 0) return;
  const Ring *K = M->get_ring();
  ring_elem one = K->one();
  ring_elem minus_one = K->minus_one();

  // After using the pivot element, it is moved to [nrows-1,ncols-1]
  // and nrows and ncols are decremented.

  MutableMatrix::iterator *p = M->begin();
  for (int i=0; i<=nc; i++)
    {
      p->set(i);
      for (; p->valid(); p->next())
        {
          int pivot_type = 0;
          ring_elem coef;
          p->copy_ring_elem(coef);
          if (K->is_equal(one, coef))
            pivot_type = 1;
          else if (K->is_equal(minus_one, coef))
            pivot_type = -1;
          if (pivot_type != 0)
            {
              perform_reduction(M, p->row(), i, nr--, nc--, pivot_type);
              if (nr < 0 || nc < 0) return;
              // restart loop with the (new) column i
              i = -1;
              break;
            }
        }
    }

  // Now search for other possible pivots
  for (int i=0; i<=nc; i++)
    {
      p->set(i);
      for (; p->valid(); p->next())
        {
          ring_elem coef;
          p->copy_ring_elem(coef);
          if (!K->is_unit(coef)) continue;
          int pivot_type = 0;
          if (K->is_equal(one, coef))
            pivot_type = 1;
          else if (K->is_equal(minus_one, coef))
            pivot_type = -1;

          perform_reduction(M, p->row(), i, nr--, nc--, pivot_type);
          if (nr < 0 || nc < 0) return;
          // restart loop with the (new) column i
          i = -1;
          break;
        }
    }
}
Ejemplo n.º 2
0
/* Graph reduction function. Destructively modifies the graph passed in.
 */
enum graphReductionResult
reduce_graph(struct node *root)
{
	enum graphReductionResult r = UNKNOWN;

	struct spine_stack *stack = NULL;

	unsigned long reduction_counter = 0;
	int max_redex_count = 0;

	/* Used to decide what to do next:
	 * at an application (interior node of graph)
	 * you can take the left branch into subtree,
	 * take the right branch, or pop the node and
	 * go "up" the tree. */
	enum Direction { DIR_LEFT, DIR_RIGHT, DIR_UP };
	enum Direction dir = DIR_LEFT;

	stack = new_spine_stack(64);

	/* root constitutes the "dummy" root node */
	root->updateable = root->left_addr;
	pushnode(stack, root, 1);

	D print_graph(root, 0, TOPNODE(stack)->sn);

	while (STACK_NOT_EMPTY(stack))
	{
		int pop_stack_cnt = 1;
		int performed_reduction = 0;
		struct node *topnode = TOPNODE(stack);
		const char *atom_name = NULL;

		switch (topnode->typ)
		{
		case APPLICATION:
			switch (dir)
			{
			case DIR_LEFT:
				topnode->updateable = topnode->left_addr;
				pushnode(stack, topnode->left, 0);
				D printf("push left branch on stack, depth now %d\n", DEPTH(stack));
				pop_stack_cnt = 0;
				break;

			case DIR_RIGHT:
				topnode->updateable = topnode->right_addr;
				pushnode(stack, topnode->right, 2);
				D printf("push right branch on stack, depth now %d\n", DEPTH(stack));
				pop_stack_cnt = 0;
				break;

			case DIR_UP:
				break;
			}
			break;

		case ATOM:
			/* node->typ indicates a combinator, which can comprise a built-in,
			 * or it can comprise a mere variable. Let node->rule decide. */
			if (topnode->rule && DEPTH(stack) >= (topnode->rule->required_depth + 2))
			{
				D {
					atom_name = topnode->name;
					printf("%s reduction (sn %d), stack depth %d, before: ",
						topnode->name,
						topnode->sn,
					 	DEPTH(stack)
					);
					print_graph(root->left, topnode->sn, topnode->sn);
				}

				pop_stack_cnt = topnode->rule->required_depth + 1;

				perform_reduction(stack);

				performed_reduction = 1;

			} else D {
				printf("%s atom, stack depth %d, required depth %d.\n",
					topnode->name,
				 	DEPTH(stack),
					topnode->rule? topnode->rule->required_depth + 2: -1
				);
			}
			if (performed_reduction) SS;
			break;
		}