text:
#include <isl/id.h>
#include <isl/val.h>
#include <isl/space.h>
#include <isl/map.h>
#include <isl_schedule_band.h>
#include <isl_schedule_private.h>

#undef EL
#define EL isl_schedule_tree

#include <isl_list_templ.h>

#undef EL_BASE
#define EL_BASE schedule_tree

#include <isl_list_templ.c>

/* Is "tree" the leaf of a schedule tree?
 */
int isl_schedule_tree_is_leaf(__isl_keep isl_schedule_tree *tree)
{
	return isl_schedule_tree_get_type(tree) == isl_schedule_node_leaf;
}

/* Create a new schedule tree of type "type".
 * The caller is responsible for filling in the type specific fields and
 * the children.
 *
 * By default, the single node tree does not have any anchored nodes.
 * The caller is responsible for updating the anchored field if needed.
 */
static __isl_give isl_schedule_tree *isl_schedule_tree_alloc(isl_ctx *ctx,
	enum isl_schedule_node_type type)
{
	isl_schedule_tree *tree;

	if (type == isl_schedule_node_error)
		return NULL;

	tree = isl_calloc_type(ctx, isl_schedule_tree);
	if (!tree)
		return NULL;

	tree->ref = 1;
	tree->ctx = ctx;
	isl_ctx_ref(ctx);
	tree->type = type;
	tree->anchored = 0;

	return tree;
}

/* Return a fresh copy of "tree".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_dup(
	__isl_keep isl_schedule_tree *tree)
{
	isl_ctx *ctx;
	isl_schedule_tree *dup;

	if (!tree)
		return NULL;

	ctx = isl_schedule_tree_get_ctx(tree);
	dup = isl_schedule_tree_alloc(ctx, tree->type);
	if (!dup)
		return NULL;

	switch (tree->type) {
	case isl_schedule_node_error:
		isl_die(ctx, isl_error_internal,
			"allocation should have failed",
			return isl_schedule_tree_free(dup));
	case isl_schedule_node_band:
		dup->band = isl_schedule_band_copy(tree->band);
		if (!dup->band)
			return isl_schedule_tree_free(dup);
		break;
	case isl_schedule_node_context:
		dup->context = isl_set_copy(tree->context);
		if (!dup->context)
			return isl_schedule_tree_free(dup);
		break;
	case isl_schedule_node_domain:
		dup->domain = isl_union_set_copy(tree->domain);
		if (!dup->domain)
			return isl_schedule_tree_free(dup);
		break;
	case isl_schedule_node_expansion:
		dup->contraction =
			isl_union_pw_multi_aff_copy(tree->contraction);
		dup->expansion = isl_union_map_copy(tree->expansion);
		if (!dup->contraction || !dup->expansion)
			return isl_schedule_tree_free(dup);
		break;
	case isl_schedule_node_extension:
		dup->extension = isl_union_map_copy(tree->extension);
		if (!dup->extension)
			return isl_schedule_tree_free(dup);
		break;
	case isl_schedule_node_filter:
		dup->filter = isl_union_set_copy(tree->filter);
		if (!dup->filter)
			return isl_schedule_tree_free(dup);
		break;
	case isl_schedule_node_guard:
		dup->guard = isl_set_copy(tree->guard);
		if (!dup->guard)
			return isl_schedule_tree_free(dup);
		break;
	case isl_schedule_node_mark:
		dup->mark = isl_id_copy(tree->mark);
		if (!dup->mark)
			return isl_schedule_tree_free(dup);
		break;
	case isl_schedule_node_leaf:
	case isl_schedule_node_sequence:
	case isl_schedule_node_set:
		break;
	}

	if (tree->children) {
		dup->children = isl_schedule_tree_list_copy(tree->children);
		if (!dup->children)
			return isl_schedule_tree_free(dup);
	}
	dup->anchored = tree->anchored;

	return dup;
}

/* Return an isl_schedule_tree that is equal to "tree" and that has only
 * a single reference.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_cow(
	__isl_take isl_schedule_tree *tree)
{
	if (!tree)
		return NULL;

	if (tree->ref == 1)
		return tree;
	tree->ref--;
	return isl_schedule_tree_dup(tree);
}

/* Return a new reference to "tree".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_copy(
	__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return NULL;

	tree->ref++;
	return tree;
}

/* Free "tree" and return NULL.
 */
__isl_null isl_schedule_tree *isl_schedule_tree_free(
	__isl_take isl_schedule_tree *tree)
{
	if (!tree)
		return NULL;
	if (--tree->ref > 0)
		return NULL;

	switch (tree->type) {
	case isl_schedule_node_band:
		isl_schedule_band_free(tree->band);
		break;
	case isl_schedule_node_context:
		isl_set_free(tree->context);
		break;
	case isl_schedule_node_domain:
		isl_union_set_free(tree->domain);
		break;
	case isl_schedule_node_expansion:
		isl_union_pw_multi_aff_free(tree->contraction);
		isl_union_map_free(tree->expansion);
		break;
	case isl_schedule_node_extension:
		isl_union_map_free(tree->extension);
		break;
	case isl_schedule_node_filter:
		isl_union_set_free(tree->filter);
		break;
	case isl_schedule_node_guard:
		isl_set_free(tree->guard);
		break;
	case isl_schedule_node_mark:
		isl_id_free(tree->mark);
		break;
	case isl_schedule_node_sequence:
	case isl_schedule_node_set:
	case isl_schedule_node_error:
	case isl_schedule_node_leaf:
		break;
	}
	isl_schedule_tree_list_free(tree->children);
	isl_ctx_deref(tree->ctx);
	free(tree);

	return NULL;
}

/* Create and return a new leaf schedule tree.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_leaf(isl_ctx *ctx)
{
	return isl_schedule_tree_alloc(ctx, isl_schedule_node_leaf);
}

/* Create a new band schedule tree referring to "band"
 * with no children.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_from_band(
	__isl_take isl_schedule_band *band)
{
	isl_ctx *ctx;
	isl_schedule_tree *tree;

	if (!band)
		return NULL;

	ctx = isl_schedule_band_get_ctx(band);
	tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_band);
	if (!tree)
		goto error;

	tree->band = band;
	tree->anchored = isl_schedule_band_is_anchored(band);

	return tree;
error:
	isl_schedule_band_free(band);
	return NULL;
}

/* Create a new context schedule tree with the given context and no children.
 * Since the context references the outer schedule dimension,
 * the tree is anchored.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_from_context(
	__isl_take isl_set *context)
{
	isl_ctx *ctx;
	isl_schedule_tree *tree;

	if (!context)
		return NULL;

	ctx = isl_set_get_ctx(context);
	tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_context);
	if (!tree)
		goto error;

	tree->context = context;
	tree->anchored = 1;

	return tree;
error:
	isl_set_free(context);
	return NULL;
}

/* Create a new domain schedule tree with the given domain and no children.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_from_domain(
	__isl_take isl_union_set *domain)
{
	isl_ctx *ctx;
	isl_schedule_tree *tree;

	if (!domain)
		return NULL;

	ctx = isl_union_set_get_ctx(domain);
	tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_domain);
	if (!tree)
		goto error;

	tree->domain = domain;

	return tree;
error:
	isl_union_set_free(domain);
	return NULL;
}

/* Create a new expansion schedule tree with the given contraction and
 * expansion and no children.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_from_expansion(
	__isl_take isl_union_pw_multi_aff *contraction,
	__isl_take isl_union_map *expansion)
{
	isl_ctx *ctx;
	isl_schedule_tree *tree;

	if (!contraction || !expansion)
		goto error;

	ctx = isl_union_map_get_ctx(expansion);
	tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_expansion);
	if (!tree)
		goto error;

	tree->contraction = contraction;
	tree->expansion = expansion;

	return tree;
error:
	isl_union_pw_multi_aff_free(contraction);
	isl_union_map_free(expansion);
	return NULL;
}

/* Create a new extension schedule tree with the given extension and
 * no children.
 * Since the domain of the extension refers to the outer schedule dimension,
 * the tree is anchored.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_from_extension(
	__isl_take isl_union_map *extension)
{
	isl_ctx *ctx;
	isl_schedule_tree *tree;

	if (!extension)
		return NULL;

	ctx = isl_union_map_get_ctx(extension);
	tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_extension);
	if (!tree)
		goto error;

	tree->extension = extension;
	tree->anchored = 1;

	return tree;
error:
	isl_union_map_free(extension);
	return NULL;
}

/* Create a new filter schedule tree with the given filter and no children.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_from_filter(
	__isl_take isl_union_set *filter)
{
	isl_ctx *ctx;
	isl_schedule_tree *tree;

	if (!filter)
		return NULL;

	ctx = isl_union_set_get_ctx(filter);
	tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_filter);
	if (!tree)
		goto error;

	tree->filter = filter;

	return tree;
error:
	isl_union_set_free(filter);
	return NULL;
}

/* Create a new guard schedule tree with the given guard and no children.
 * Since the guard references the outer schedule dimension,
 * the tree is anchored.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_from_guard(
	__isl_take isl_set *guard)
{
	isl_ctx *ctx;
	isl_schedule_tree *tree;

	if (!guard)
		return NULL;

	ctx = isl_set_get_ctx(guard);
	tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_guard);
	if (!tree)
		goto error;

	tree->guard = guard;
	tree->anchored = 1;

	return tree;
error:
	isl_set_free(guard);
	return NULL;
}

/* Create a new mark schedule tree with the given mark identifier and
 * no children.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_from_mark(
	__isl_take isl_id *mark)
{
	isl_ctx *ctx;
	isl_schedule_tree *tree;

	if (!mark)
		return NULL;

	ctx = isl_id_get_ctx(mark);
	tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_mark);
	if (!tree)
		goto error;

	tree->mark = mark;

	return tree;
error:
	isl_id_free(mark);
	return NULL;
}

/* Does "tree" have any node that depends on its position
 * in the complete schedule tree?
 */
isl_bool isl_schedule_tree_is_subtree_anchored(
	__isl_keep isl_schedule_tree *tree)
{
	return tree ? isl_bool_ok(tree->anchored) : isl_bool_error;
}

/* Does the root node of "tree" depend on its position in the complete
 * schedule tree?
 * Band nodes may be anchored depending on the associated AST build options.
 * Context, extension and guard nodes are always anchored.
 */
int isl_schedule_tree_is_anchored(__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return -1;

	switch (isl_schedule_tree_get_type(tree)) {
	case isl_schedule_node_error:
		return -1;
	case isl_schedule_node_band:
		return isl_schedule_band_is_anchored(tree->band);
	case isl_schedule_node_context:
	case isl_schedule_node_extension:
	case isl_schedule_node_guard:
		return 1;
	case isl_schedule_node_domain:
	case isl_schedule_node_expansion:
	case isl_schedule_node_filter:
	case isl_schedule_node_leaf:
	case isl_schedule_node_mark:
	case isl_schedule_node_sequence:
	case isl_schedule_node_set:
		return 0;
	}

	isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
		"unhandled case", return -1);
}

/* Update the anchored field of "tree" based on whether the root node
 * itself in anchored and the anchored fields of the children.
 *
 * This function should be called whenever the children of a tree node
 * are changed or the anchoredness of the tree root itself changes.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_update_anchored(
	__isl_take isl_schedule_tree *tree)
{
	int i;
	isl_size n;
	int anchored;

	anchored = isl_schedule_tree_is_anchored(tree);
	n = isl_schedule_tree_n_children(tree);
	if (anchored < 0 || n < 0)
		return isl_schedule_tree_free(tree);

	for (i = 0; !anchored && i < n; ++i) {
		isl_schedule_tree *child;

		child = isl_schedule_tree_get_child(tree, i);
		if (!child)
			return isl_schedule_tree_free(tree);
		anchored = child->anchored;
		isl_schedule_tree_free(child);
	}

	if (anchored == tree->anchored)
		return tree;
	tree = isl_schedule_tree_cow(tree);
	if (!tree)
		return NULL;
	tree->anchored = anchored;
	return tree;
}

/* Create a new tree of the given type (isl_schedule_node_sequence or
 * isl_schedule_node_set) with the given children.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_from_children(
	enum isl_schedule_node_type type,
	__isl_take isl_schedule_tree_list *list)
{
	isl_ctx *ctx;
	isl_schedule_tree *tree;

	if (!list)
		return NULL;

	ctx = isl_schedule_tree_list_get_ctx(list);
	tree = isl_schedule_tree_alloc(ctx, type);
	if (!tree)
		goto error;

	tree->children = list;
	tree = isl_schedule_tree_update_anchored(tree);

	return tree;
error:
	isl_schedule_tree_list_free(list);
	return NULL;
}

/* Construct a tree with a root node of type "type" and as children
 * "tree1" and "tree2".
 * If the root of one (or both) of the input trees is itself of type "type",
 * then the tree is replaced by its children.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_from_pair(
	enum isl_schedule_node_type type, __isl_take isl_schedule_tree *tree1,
	__isl_take isl_schedule_tree *tree2)
{
	isl_ctx *ctx;
	isl_schedule_tree_list *list;

	if (!tree1 || !tree2)
		goto error;

	ctx = isl_schedule_tree_get_ctx(tree1);
	if (isl_schedule_tree_get_type(tree1) == type) {
		list = isl_schedule_tree_list_copy(tree1->children);
		isl_schedule_tree_free(tree1);
	} else {
		list = isl_schedule_tree_list_alloc(ctx, 2);
		list = isl_schedule_tree_list_add(list, tree1);
	}
	if (isl_schedule_tree_get_type(tree2) == type) {
		isl_schedule_tree_list *children;

		children = isl_schedule_tree_list_copy(tree2->children);
		list = isl_schedule_tree_list_concat(list, children);
		isl_schedule_tree_free(tree2);
	} else {
		list = isl_schedule_tree_list_add(list, tree2);
	}

	return isl_schedule_tree_from_children(type, list);
error:
	isl_schedule_tree_free(tree1);
	isl_schedule_tree_free(tree2);
	return NULL;
}

/* Construct a tree with a sequence root node and as children
 * "tree1" and "tree2".
 * If the root of one (or both) of the input trees is itself a sequence,
 * then the tree is replaced by its children.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_sequence_pair(
	__isl_take isl_schedule_tree *tree1,
	__isl_take isl_schedule_tree *tree2)
{
	return isl_schedule_tree_from_pair(isl_schedule_node_sequence,
						tree1, tree2);
}

/* Construct a tree with a set root node and as children
 * "tree1" and "tree2".
 * If the root of one (or both) of the input trees is itself a set,
 * then the tree is replaced by its children.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_set_pair(
	__isl_take isl_schedule_tree *tree1,
	__isl_take isl_schedule_tree *tree2)
{
	return isl_schedule_tree_from_pair(isl_schedule_node_set, tree1, tree2);
}

/* Return the isl_ctx to which "tree" belongs.
 */
isl_ctx *isl_schedule_tree_get_ctx(__isl_keep isl_schedule_tree *tree)
{
	return tree ? tree->ctx : NULL;
}

/* Return the type of the root of the tree or isl_schedule_node_error
 * on error.
 */
enum isl_schedule_node_type isl_schedule_tree_get_type(
	__isl_keep isl_schedule_tree *tree)
{
	return tree ? tree->type : isl_schedule_node_error;
}

/* Are "tree1" and "tree2" obviously equal to each other?
 */
isl_bool isl_schedule_tree_plain_is_equal(__isl_keep isl_schedule_tree *tree1,
	__isl_keep isl_schedule_tree *tree2)
{
	isl_bool equal;
	int i;
	isl_size n1, n2;

	if (!tree1 || !tree2)
		return isl_bool_error;
	if (tree1 == tree2)
		return isl_bool_true;
	if (tree1->type != tree2->type)
		return isl_bool_false;

	switch (tree1->type) {
	case isl_schedule_node_band:
		equal = isl_schedule_band_plain_is_equal(tree1->band,
							tree2->band);
		break;
	case isl_schedule_node_context:
		equal = isl_set_is_equal(tree1->context, tree2->context);
		break;
	case isl_schedule_node_domain:
		equal = isl_union_set_is_equal(tree1->domain, tree2->domain);
		break;
	case isl_schedule_node_expansion:
		equal = isl_union_map_is_equal(tree1->expansion,
						tree2->expansion);
		if (equal >= 0 && equal)
			equal = isl_union_pw_multi_aff_plain_is_equal(
				    tree1->contraction, tree2->contraction);
		break;
	case isl_schedule_node_extension:
		equal = isl_union_map_is_equal(tree1->extension,
						tree2->extension);
		break;
	case isl_schedule_node_filter:
		equal = isl_union_set_is_equal(tree1->filter, tree2->filter);
		break;
	case isl_schedule_node_guard:
		equal = isl_set_is_equal(tree1->guard, tree2->guard);
		break;
	case isl_schedule_node_mark:
		equal = isl_bool_ok(tree1->mark == tree2->mark);
		break;
	case isl_schedule_node_leaf:
	case isl_schedule_node_sequence:
	case isl_schedule_node_set:
		equal = isl_bool_true;
		break;
	case isl_schedule_node_error:
		equal = isl_bool_error;
		break;
	}

	if (equal < 0 || !equal)
		return equal;

	n1 = isl_schedule_tree_n_children(tree1);
	n2 = isl_schedule_tree_n_children(tree2);
	if (n1 < 0 || n2 < 0)
		return isl_bool_error;
	if (n1 != n2)
		return isl_bool_false;
	for (i = 0; i < n1; ++i) {
		isl_schedule_tree *child1, *child2;

		child1 = isl_schedule_tree_get_child(tree1, i);
		child2 = isl_schedule_tree_get_child(tree2, i);
		equal = isl_schedule_tree_plain_is_equal(child1, child2);
		isl_schedule_tree_free(child1);
		isl_schedule_tree_free(child2);

		if (equal < 0 || !equal)
			return equal;
	}

	return isl_bool_true;
}

/* Does "tree" have any children, other than an implicit leaf.
 */
int isl_schedule_tree_has_children(__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return -1;

	return tree->children != NULL;
}

/* Return the number of children of "tree", excluding implicit leaves.
 * The "children" field is NULL if there are
 * no children (except for the implicit leaves).
 */
isl_size isl_schedule_tree_n_children(__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return isl_size_error;

	if (!tree->children)
		return 0;
	return isl_schedule_tree_list_n_schedule_tree(tree->children);
}

/* Return a copy of the (explicit) child at position "pos" of "tree".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_get_child(
	__isl_keep isl_schedule_tree *tree, int pos)
{
	if (!tree)
		return NULL;
	if (!tree->children)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
			"schedule tree has no explicit children", return NULL);
	return isl_schedule_tree_list_get_schedule_tree(tree->children, pos);
}

/* Return a copy of the (explicit) child at position "pos" of "tree" and
 * free "tree".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_child(
	__isl_take isl_schedule_tree *tree, int pos)
{
	isl_schedule_tree *child;

	child = isl_schedule_tree_get_child(tree, pos);
	isl_schedule_tree_free(tree);
	return child;
}

/* Remove all (explicit) children from "tree".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_reset_children(
	__isl_take isl_schedule_tree *tree)
{
	tree = isl_schedule_tree_cow(tree);
	if (!tree)
		return NULL;
	tree->children = isl_schedule_tree_list_free(tree->children);
	return tree;
}

/* Remove the child at position "pos" from the children of "tree".
 * If there was only one child to begin with, then remove all children.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_drop_child(
	__isl_take isl_schedule_tree *tree, int pos)
{
	isl_size n;

	tree = isl_schedule_tree_cow(tree);

	n = isl_schedule_tree_n_children(tree);
	if (n < 0)
		return isl_schedule_tree_free(tree);
	if (n == 0)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"tree does not have any explicit children",
			return isl_schedule_tree_free(tree));
	if (pos < 0 || pos >= n)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"position out of bounds",
			return isl_schedule_tree_free(tree));
	if (n == 1)
		return isl_schedule_tree_reset_children(tree);

	tree->children = isl_schedule_tree_list_drop(tree->children, pos, 1);
	if (!tree->children)
		return isl_schedule_tree_free(tree);

	return tree;
}

/* Replace the child at position "pos" of "tree" by "child".
 *
 * If the new child is a leaf, then it is not explicitly
 * recorded in the list of children.  Instead, the list of children
 * (which is assumed to have only one element) is removed.
 * Note that the children of set and sequence nodes are always
 * filters, so they cannot be replaced by empty trees.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_replace_child(
	__isl_take isl_schedule_tree *tree, int pos,
	__isl_take isl_schedule_tree *child)
{
	tree = isl_schedule_tree_cow(tree);
	if (!tree || !child)
		goto error;

	if (isl_schedule_tree_is_leaf(child)) {
		isl_size n;

		isl_schedule_tree_free(child);
		if (!tree->children && pos == 0)
			return tree;
		n = isl_schedule_tree_n_children(tree);
		if (n < 0)
			return isl_schedule_tree_free(tree);
		if (n != 1)
			isl_die(isl_schedule_tree_get_ctx(tree),
				isl_error_internal,
				"can only replace single child by leaf",
				goto error);
		return isl_schedule_tree_reset_children(tree);
	}

	if (!tree->children && pos == 0)
		tree->children =
			isl_schedule_tree_list_from_schedule_tree(child);
	else
		tree->children = isl_schedule_tree_list_set_schedule_tree(
				tree->children, pos, child);

	if (!tree->children)
		return isl_schedule_tree_free(tree);
	tree = isl_schedule_tree_update_anchored(tree);

	return tree;
error:
	isl_schedule_tree_free(tree);
	isl_schedule_tree_free(child);
	return NULL;
}

/* Replace the (explicit) children of "tree" by "children"?
 */
__isl_give isl_schedule_tree *isl_schedule_tree_set_children(
	__isl_take isl_schedule_tree *tree,
	__isl_take isl_schedule_tree_list *children)
{
	tree = isl_schedule_tree_cow(tree);
	if (!tree || !children)
		goto error;
	isl_schedule_tree_list_free(tree->children);
	tree->children = children;
	return tree;
error:
	isl_schedule_tree_free(tree);
	isl_schedule_tree_list_free(children);
	return NULL;
}

/* Create a new band schedule tree referring to "band"
 * with "tree" as single child.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_insert_band(
	__isl_take isl_schedule_tree *tree, __isl_take isl_schedule_band *band)
{
	isl_schedule_tree *res;

	res = isl_schedule_tree_from_band(band);
	return isl_schedule_tree_replace_child(res, 0, tree);
}

/* Create a new context schedule tree with the given context and
 * with "tree" as single child.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_insert_context(
	__isl_take isl_schedule_tree *tree, __isl_take isl_set *context)
{
	isl_schedule_tree *res;

	res = isl_schedule_tree_from_context(context);
	return isl_schedule_tree_replace_child(res, 0, tree);
}

/* Create a new domain schedule tree with the given domain and
 * with "tree" as single child.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_insert_domain(
	__isl_take isl_schedule_tree *tree, __isl_take isl_union_set *domain)
{
	isl_schedule_tree *res;

	res = isl_schedule_tree_from_domain(domain);
	return isl_schedule_tree_replace_child(res, 0, tree);
}

/* Create a new expansion schedule tree with the given contraction and
 * expansion and with "tree" as single child.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_insert_expansion(
	__isl_take isl_schedule_tree *tree,
	__isl_take isl_union_pw_multi_aff *contraction,
	__isl_take isl_union_map *expansion)
{
	isl_schedule_tree *res;

	res = isl_schedule_tree_from_expansion(contraction, expansion);
	return isl_schedule_tree_replace_child(res, 0, tree);
}

/* Create a new extension schedule tree with the given extension and
 * with "tree" as single child.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_insert_extension(
	__isl_take isl_schedule_tree *tree, __isl_take isl_union_map *extension)
{
	isl_schedule_tree *res;

	res = isl_schedule_tree_from_extension(extension);
	return isl_schedule_tree_replace_child(res, 0, tree);
}

/* Create a new filter schedule tree with the given filter and single child.
 *
 * If the root of "tree" is itself a filter node, then the two
 * filter nodes are merged into one node.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_insert_filter(
	__isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter)
{
	isl_schedule_tree *res;

	if (isl_schedule_tree_get_type(tree) == isl_schedule_node_filter) {
		isl_union_set *tree_filter;

		tree_filter = isl_schedule_tree_filter_get_filter(tree);
		tree_filter = isl_union_set_intersect(tree_filter, filter);
		tree = isl_schedule_tree_filter_set_filter(tree, tree_filter);
		return tree;
	}

	res = isl_schedule_tree_from_filter(filter);
	return isl_schedule_tree_replace_child(res, 0, tree);
}

/* Insert a filter node with filter set "filter"
 * in each of the children of "tree".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_children_insert_filter(
	__isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter)
{
	int i;
	isl_size n;

	n = isl_schedule_tree_n_children(tree);
	if (n < 0 || !filter)
		goto error;

	for (i = 0; i < n; ++i) {
		isl_schedule_tree *child;

		child = isl_schedule_tree_get_child(tree, i);
		child = isl_schedule_tree_insert_filter(child,
						    isl_union_set_copy(filter));
		tree = isl_schedule_tree_replace_child(tree, i, child);
	}

	isl_union_set_free(filter);
	return tree;
error:
	isl_union_set_free(filter);
	isl_schedule_tree_free(tree);
	return NULL;
}

/* Create a new guard schedule tree with the given guard and
 * with "tree" as single child.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_insert_guard(
	__isl_take isl_schedule_tree *tree, __isl_take isl_set *guard)
{
	isl_schedule_tree *res;

	res = isl_schedule_tree_from_guard(guard);
	return isl_schedule_tree_replace_child(res, 0, tree);
}

/* Create a new mark schedule tree with the given mark identifier and
 * single child.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_insert_mark(
	__isl_take isl_schedule_tree *tree, __isl_take isl_id *mark)
{
	isl_schedule_tree *res;

	res = isl_schedule_tree_from_mark(mark);
	return isl_schedule_tree_replace_child(res, 0, tree);
}

/* Return the number of members in the band tree root.
 */
isl_size isl_schedule_tree_band_n_member(__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return isl_size_error;

	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return isl_size_error);

	return isl_schedule_band_n_member(tree->band);
}

/* Is the band member at position "pos" of the band tree root
 * marked coincident?
 */
isl_bool isl_schedule_tree_band_member_get_coincident(
	__isl_keep isl_schedule_tree *tree, int pos)
{
	if (!tree)
		return isl_bool_error;

	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return isl_bool_error);

	return isl_schedule_band_member_get_coincident(tree->band, pos);
}

/* Mark the given band member as being coincident or not
 * according to "coincident".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_band_member_set_coincident(
	__isl_take isl_schedule_tree *tree, int pos, int coincident)
{
	if (!tree)
		return NULL;
	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return isl_schedule_tree_free(tree));
	if (isl_schedule_tree_band_member_get_coincident(tree, pos) ==
								    coincident)
		return tree;
	tree = isl_schedule_tree_cow(tree);
	if (!tree)
		return NULL;

	tree->band = isl_schedule_band_member_set_coincident(tree->band, pos,
							coincident);
	if (!tree->band)
		return isl_schedule_tree_free(tree);
	return tree;
}

/* Is the band tree root marked permutable?
 */
isl_bool isl_schedule_tree_band_get_permutable(
	__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return isl_bool_error;

	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return isl_bool_error);

	return isl_schedule_band_get_permutable(tree->band);
}

/* Mark the band tree root permutable or not according to "permutable"?
 */
__isl_give isl_schedule_tree *isl_schedule_tree_band_set_permutable(
	__isl_take isl_schedule_tree *tree, int permutable)
{
	if (!tree)
		return NULL;
	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return isl_schedule_tree_free(tree));
	if (isl_schedule_tree_band_get_permutable(tree) == permutable)
		return tree;
	tree = isl_schedule_tree_cow(tree);
	if (!tree)
		return NULL;

	tree->band = isl_schedule_band_set_permutable(tree->band, permutable);
	if (!tree->band)
		return isl_schedule_tree_free(tree);
	return tree;
}

/* Return the schedule space of the band tree root.
 */
__isl_give isl_space *isl_schedule_tree_band_get_space(
	__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return NULL;

	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return NULL);

	return isl_schedule_band_get_space(tree->band);
}

/* Intersect the domain of the band schedule of the band tree root
 * with "domain".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_band_intersect_domain(
	__isl_take isl_schedule_tree *tree, __isl_take isl_union_set *domain)
{
	if (!tree || !domain)
		goto error;

	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", goto error);

	tree->band = isl_schedule_band_intersect_domain(tree->band, domain);
	if (!tree->band)
		return isl_schedule_tree_free(tree);

	return tree;
error:
	isl_schedule_tree_free(tree);
	isl_union_set_free(domain);
	return NULL;
}

/* Return the schedule of the band tree root in isolation.
 */
__isl_give isl_multi_union_pw_aff *isl_schedule_tree_band_get_partial_schedule(
	__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return NULL;

	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return NULL);

	return isl_schedule_band_get_partial_schedule(tree->band);
}

/* Replace the schedule of the band tree root by "schedule".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_band_set_partial_schedule(
	__isl_take isl_schedule_tree *tree,
	__isl_take isl_multi_union_pw_aff *schedule)
{
	tree = isl_schedule_tree_cow(tree);
	if (!tree || !schedule)
		goto error;

	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return NULL);
	tree->band = isl_schedule_band_set_partial_schedule(tree->band,
								schedule);

	return tree;
error:
	isl_schedule_tree_free(tree);
	isl_multi_union_pw_aff_free(schedule);
	return NULL;
}

/* Return the loop AST generation type for the band member
 * of the band tree root at position "pos".
 */
enum isl_ast_loop_type isl_schedule_tree_band_member_get_ast_loop_type(
	__isl_keep isl_schedule_tree *tree, int pos)
{
	if (!tree)
		return isl_ast_loop_error;

	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return isl_ast_loop_error);

	return isl_schedule_band_member_get_ast_loop_type(tree->band, pos);
}

/* Set the loop AST generation type for the band member of the band tree root
 * at position "pos" to "type".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_band_member_set_ast_loop_type(
	__isl_take isl_schedule_tree *tree, int pos,
	enum isl_ast_loop_type type)
{
	tree = isl_schedule_tree_cow(tree);
	if (!tree)
		return NULL;

	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return isl_schedule_tree_free(tree));

	tree->band = isl_schedule_band_member_set_ast_loop_type(tree->band,
								pos, type);
	if (!tree->band)
		return isl_schedule_tree_free(tree);

	return tree;
}

/* Return the loop AST generation type for the band member
 * of the band tree root at position "pos" for the isolated part.
 */
enum isl_ast_loop_type isl_schedule_tree_band_member_get_isolate_ast_loop_type(
	__isl_keep isl_schedule_tree *tree, int pos)
{
	if (!tree)
		return isl_ast_loop_error;

	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return isl_ast_loop_error);

	return isl_schedule_band_member_get_isolate_ast_loop_type(tree->band,
									pos);
}

/* Set the loop AST generation type for the band member of the band tree root
 * at position "pos" for the isolated part to "type".
 */
__isl_give isl_schedule_tree *
isl_schedule_tree_band_member_set_isolate_ast_loop_type(
	__isl_take isl_schedule_tree *tree, int pos,
	enum isl_ast_loop_type type)
{
	tree = isl_schedule_tree_cow(tree);
	if (!tree)
		return NULL;

	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return isl_schedule_tree_free(tree));

	tree->band = isl_schedule_band_member_set_isolate_ast_loop_type(
							tree->band, pos, type);
	if (!tree->band)
		return isl_schedule_tree_free(tree);

	return tree;
}

/* Return the AST build options associated to the band tree root.
 */
__isl_give isl_union_set *isl_schedule_tree_band_get_ast_build_options(
	__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return NULL;

	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return NULL);

	return isl_schedule_band_get_ast_build_options(tree->band);
}

/* Replace the AST build options associated to band tree root by "options".
 * Updated the anchored field if the anchoredness of the root node itself
 * changes.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_band_set_ast_build_options(
	__isl_take isl_schedule_tree *tree, __isl_take isl_union_set *options)
{
	int was_anchored;

	tree = isl_schedule_tree_cow(tree);
	if (!tree || !options)
		goto error;

	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", goto error);

	was_anchored = isl_schedule_tree_is_anchored(tree);
	tree->band = isl_schedule_band_set_ast_build_options(tree->band,
								options);
	if (!tree->band)
		return isl_schedule_tree_free(tree);
	if (isl_schedule_tree_is_anchored(tree) != was_anchored)
		tree = isl_schedule_tree_update_anchored(tree);

	return tree;
error:
	isl_schedule_tree_free(tree);
	isl_union_set_free(options);
	return NULL;
}

/* Return the "isolate" option associated to the band tree root of "tree",
 * which is assumed to appear at schedule depth "depth".
 */
__isl_give isl_set *isl_schedule_tree_band_get_ast_isolate_option(
	__isl_keep isl_schedule_tree *tree, int depth)
{
	if (!tree)
		return NULL;

	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return NULL);

	return isl_schedule_band_get_ast_isolate_option(tree->band, depth);
}

/* Return the context of the context tree root.
 */
__isl_give isl_set *isl_schedule_tree_context_get_context(
	__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return NULL;

	if (tree->type != isl_schedule_node_context)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a context node", return NULL);

	return isl_set_copy(tree->context);
}

/* Return the domain of the domain tree root.
 */
__isl_give isl_union_set *isl_schedule_tree_domain_get_domain(
	__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return NULL;

	if (tree->type != isl_schedule_node_domain)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a domain node", return NULL);

	return isl_union_set_copy(tree->domain);
}

/* Replace the domain of domain tree root "tree" by "domain".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_domain_set_domain(
	__isl_take isl_schedule_tree *tree, __isl_take isl_union_set *domain)
{
	tree = isl_schedule_tree_cow(tree);
	if (!tree || !domain)
		goto error;

	if (tree->type != isl_schedule_node_domain)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a domain node", goto error);

	isl_union_set_free(tree->domain);
	tree->domain = domain;

	return tree;
error:
	isl_schedule_tree_free(tree);
	isl_union_set_free(domain);
	return NULL;
}

/* Return the contraction of the expansion tree root.
 */
__isl_give isl_union_pw_multi_aff *isl_schedule_tree_expansion_get_contraction(
	__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return NULL;

	if (tree->type != isl_schedule_node_expansion)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not an expansion node", return NULL);

	return isl_union_pw_multi_aff_copy(tree->contraction);
}

/* Return the expansion of the expansion tree root.
 */
__isl_give isl_union_map *isl_schedule_tree_expansion_get_expansion(
	__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return NULL;

	if (tree->type != isl_schedule_node_expansion)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not an expansion node", return NULL);

	return isl_union_map_copy(tree->expansion);
}

/* Replace the contraction and the expansion of the expansion tree root "tree"
 * by "contraction" and "expansion".
 */
__isl_give isl_schedule_tree *
isl_schedule_tree_expansion_set_contraction_and_expansion(
	__isl_take isl_schedule_tree *tree,
	__isl_take isl_union_pw_multi_aff *contraction,
	__isl_take isl_union_map *expansion)
{
	tree = isl_schedule_tree_cow(tree);
	if (!tree || !contraction || !expansion)
		goto error;

	if (tree->type != isl_schedule_node_expansion)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not an expansion node", return NULL);

	isl_union_pw_multi_aff_free(tree->contraction);
	tree->contraction = contraction;
	isl_union_map_free(tree->expansion);
	tree->expansion = expansion;

	return tree;
error:
	isl_schedule_tree_free(tree);
	isl_union_pw_multi_aff_free(contraction);
	isl_union_map_free(expansion);
	return NULL;
}

/* Return the extension of the extension tree root.
 */
__isl_give isl_union_map *isl_schedule_tree_extension_get_extension(
	__isl_take isl_schedule_tree *tree)
{
	if (!tree)
		return NULL;

	if (tree->type != isl_schedule_node_extension)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not an extension node", return NULL);

	return isl_union_map_copy(tree->extension);
}

/* Replace the extension of extension tree root "tree" by "extension".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_extension_set_extension(
	__isl_take isl_schedule_tree *tree, __isl_take isl_union_map *extension)
{
	tree = isl_schedule_tree_cow(tree);
	if (!tree || !extension)
		goto error;

	if (tree->type != isl_schedule_node_extension)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not an extension node", return NULL);
	isl_union_map_free(tree->extension);
	tree->extension = extension;

	return tree;
error:
	isl_schedule_tree_free(tree);
	isl_union_map_free(extension);
	return NULL;
}

/* Return the filter of the filter tree root.
 */
__isl_give isl_union_set *isl_schedule_tree_filter_get_filter(
	__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return NULL;

	if (tree->type != isl_schedule_node_filter)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a filter node", return NULL);

	return isl_union_set_copy(tree->filter);
}

/* Replace the filter of the filter tree root by "filter".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_filter_set_filter(
	__isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter)
{
	tree = isl_schedule_tree_cow(tree);
	if (!tree || !filter)
		goto error;

	if (tree->type != isl_schedule_node_filter)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a filter node", return NULL);

	isl_union_set_free(tree->filter);
	tree->filter = filter;

	return tree;
error:
	isl_schedule_tree_free(tree);
	isl_union_set_free(filter);
	return NULL;
}

/* Return the guard of the guard tree root.
 */
__isl_give isl_set *isl_schedule_tree_guard_get_guard(
	__isl_take isl_schedule_tree *tree)
{
	if (!tree)
		return NULL;

	if (tree->type != isl_schedule_node_guard)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a guard node", return NULL);

	return isl_set_copy(tree->guard);
}

/* Return the mark identifier of the mark tree root "tree".
 */
__isl_give isl_id *isl_schedule_tree_mark_get_id(
	__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return NULL;

	if (tree->type != isl_schedule_node_mark)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a mark node", return NULL);

	return isl_id_copy(tree->mark);
}

/* Set dim to the range dimension of "map" and abort the search.
 */
static isl_stat set_range_dim(__isl_take isl_map *map, void *user)
{
	isl_size *dim = user;

	*dim = isl_map_dim(map, isl_dim_out);
	isl_map_free(map);

	return isl_stat_error;
}

/* Return the dimension of the range of "umap".
 * "umap" is assumed not to be empty and
 * all maps inside "umap" are assumed to have the same range.
 *
 * We extract the range dimension from the first map in "umap".
 */
static isl_size range_dim(__isl_keep isl_union_map *umap)
{
	isl_size dim = isl_size_error;
	isl_size n;

	n = isl_union_map_n_map(umap);
	if (n < 0)
		return isl_size_error;
	if (n == 0)
		isl_die(isl_union_map_get_ctx(umap), isl_error_internal,
			"unexpected empty input", return isl_size_error);

	isl_union_map_foreach_map(umap, &set_range_dim, &dim);

	return dim;
}

/* Append an "extra" number of zeros to the range of "umap" and
 * return the result.
 */
static __isl_give isl_union_map *append_range(__isl_take isl_union_map *umap,
	int extra)
{
	isl_union_set *dom;
	isl_space *space;
	isl_multi_val *mv;
	isl_union_pw_multi_aff *suffix;
	isl_union_map *universe;
	isl_union_map *suffix_umap;

	universe = isl_union_map_universe(isl_union_map_copy(umap));
	dom = isl_union_map_domain(universe);
	space = isl_union_set_get_space(dom);
	space = isl_space_set_from_params(space);
	space = isl_space_add_dims(space, isl_dim_set, extra);
	mv = isl_multi_val_zero(space);

	suffix = isl_union_pw_multi_aff_multi_val_on_domain(dom, mv);
	suffix_umap = isl_union_map_from_union_pw_multi_aff(suffix);
	umap = isl_union_map_flat_range_product(umap, suffix_umap);

	return umap;
}

/* Should we skip the root of "tree" while looking for the first
 * descendant with schedule information?
 * That is, is it impossible to derive any information about
 * the iteration domain from this node?
 *
 * We do not want to skip leaf or error nodes because there is
 * no point in looking any deeper from these nodes.
 * We can only extract partial iteration domain information
 * from an extension node, but extension nodes are not supported
 * by the caller and it will error out on them.
 */
static isl_bool domain_less(__isl_keep isl_schedule_tree *tree)
{
	enum isl_schedule_node_type type;
	isl_size n;

	type = isl_schedule_tree_get_type(tree);
	switch (type) {
	case isl_schedule_node_band:
		n = isl_schedule_tree_band_n_member(tree);
		return n < 0 ? isl_bool_error : isl_bool_ok(n == 0);
	case isl_schedule_node_context:
	case isl_schedule_node_guard:
	case isl_schedule_node_mark:
		return isl_bool_true;
	case isl_schedule_node_leaf:
	case isl_schedule_node_error:
	case isl_schedule_node_domain:
	case isl_schedule_node_expansion:
	case isl_schedule_node_extension:
	case isl_schedule_node_filter:
	case isl_schedule_node_set:
	case isl_schedule_node_sequence:
		return isl_bool_false;
	}

	isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
		"unhandled case", return isl_bool_error);
}

/* Move down to the first descendant of "tree" that contains any schedule
 * information or return "leaf" if there is no such descendant.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_first_schedule_descendant(
	__isl_take isl_schedule_tree *tree, __isl_keep isl_schedule_tree *leaf)
{
	isl_bool down;

	while ((down = domain_less(tree)) == isl_bool_true) {
		if (!isl_schedule_tree_has_children(tree)) {
			isl_schedule_tree_free(tree);
			return isl_schedule_tree_copy(leaf);
		}
		tree = isl_schedule_tree_child(tree, 0);
	}

	if (down < 0)
		return isl_schedule_tree_free(tree);

	return tree;
}

static __isl_give isl_union_map *subtree_schedule_extend(
	__isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer);

/* Extend the schedule map "outer" with the subtree schedule
 * of the (single) child of "tree", if any.
 *
 * If "tree" does not have any descendants (apart from those that
 * do not carry any schedule information), then we simply return "outer".
 * Otherwise, we extend the schedule map "outer" with the subtree schedule
 * of the single child.
 */
static __isl_give isl_union_map *subtree_schedule_extend_child(
	__isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer)
{
	isl_schedule_tree *child;
	isl_union_map *res;

	if (!tree)
		return isl_union_map_free(outer);
	if (!isl_schedule_tree_has_children(tree))
		return outer;
	child = isl_schedule_tree_get_child(tree, 0);
	if (!child)
		return isl_union_map_free(outer);
	res = subtree_schedule_extend(child, outer);
	isl_schedule_tree_free(child);
	return res;
}

/* Extract the parameter space from one of the children of "tree",
 * which are assumed to be filters.
 */
static __isl_give isl_space *extract_space_from_filter_child(
	__isl_keep isl_schedule_tree *tree)
{
	isl_space *space;
	isl_union_set *dom;
	isl_schedule_tree *child;

	child = isl_schedule_tree_list_get_schedule_tree(tree->children, 0);
	dom = isl_schedule_tree_filter_get_filter(child);
	space = isl_union_set_get_space(dom);
	isl_union_set_free(dom);
	isl_schedule_tree_free(child);

	return space;
}

/* Extend the schedule map "outer" with the subtree schedule
 * of a set or sequence node.
 *
 * The schedule for the set or sequence node itself is composed of
 * pieces of the form
 *
 *	filter -> []
 *
 * or
 *
 *	filter -> [index]
 *
 * The first form is used if there is only a single child or
 * if the current node is a set node and the schedule_separate_components
 * option is not set.
 *
 * Each of the pieces above is extended with the subtree schedule of
 * the child of the corresponding filter, if any, padded with zeros
 * to ensure that all pieces have the same range dimension.
 */
static __isl_give isl_union_map *subtree_schedule_extend_from_children(
	__isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer)
{
	int i;
	isl_size n;
	isl_size dim;
	int separate;
	isl_ctx *ctx;
	isl_val *v = NULL;
	isl_multi_val *mv;
	isl_space *space;
	isl_union_map *umap;

	n = isl_schedule_tree_n_children(tree);
	if (n < 0)
		return isl_union_map_free(outer);
	if (n == 0)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
			"missing children", return isl_union_map_free(outer));

	ctx = isl_schedule_tree_get_ctx(tree);
	separate = n > 1 && (tree->type == isl_schedule_node_sequence ||
			    isl_options_get_schedule_separate_components(ctx));

	space = isl_space_params_alloc(ctx, 0);

	umap = isl_union_map_empty(isl_space_copy(space));
	space = isl_space_set_from_params(space);
	if (separate) {
		space = isl_space_add_dims(space, isl_dim_set, 1);
		v = isl_val_zero(ctx);
	}
	mv = isl_multi_val_zero(space);

	dim = isl_multi_val_dim(mv, isl_dim_set);
	if (dim < 0)
		umap = isl_union_map_free(umap);
	for (i = 0; i < n; ++i) {
		isl_multi_val *mv_copy;
		isl_union_pw_multi_aff *upma;
		isl_union_map *umap_i;
		isl_union_set *dom;
		isl_schedule_tree *child;
		isl_size dim_i;
		isl_bool empty;

		child = isl_schedule_tree_list_get_schedule_tree(
							tree->children, i);
		dom = isl_schedule_tree_filter_get_filter(child);

		if (separate) {
			mv = isl_multi_val_set_val(mv, 0, isl_val_copy(v));
			v = isl_val_add_ui(v, 1);
		}
		mv_copy = isl_multi_val_copy(mv);
		space = isl_union_set_get_space(dom);
		mv_copy = isl_multi_val_align_params(mv_copy, space);
		upma = isl_union_pw_multi_aff_multi_val_on_domain(dom, mv_copy);
		umap_i = isl_union_map_from_union_pw_multi_aff(upma);
		umap_i = isl_union_map_flat_range_product(
					    isl_union_map_copy(outer), umap_i);
		umap_i = subtree_schedule_extend_child(child, umap_i);
		isl_schedule_tree_free(child);

		empty = isl_union_map_is_empty(umap_i);
		if (empty < 0)
			umap_i = isl_union_map_free(umap_i);
		else if (empty) {
			isl_union_map_free(umap_i);
			continue;
		}

		dim_i = range_dim(umap_i);
		if (dim_i < 0) {
			umap = isl_union_map_free(umap);
		} else if (dim < dim_i) {
			umap = append_range(umap, dim_i - dim);
			dim = dim_i;
		} else if (dim_i < dim) {
			umap_i = append_range(umap_i, dim - dim_i);
		}
		umap = isl_union_map_union(umap, umap_i);
	}

	isl_val_free(v);
	isl_multi_val_free(mv);
	isl_union_map_free(outer);

	return umap;
}

/* Extend the schedule map "outer" with the subtree schedule of "tree".
 *
 * If the root of the tree is a set or a sequence, then we extend
 * the schedule map in subtree_schedule_extend_from_children.
 * Otherwise, we extend the schedule map with the partial schedule
 * corresponding to the root of the tree and then continue with
 * the single child of this root.
 * In the special case of an expansion, the schedule map is "extended"
 * by applying the expansion to the domain of the schedule map.
 */
static __isl_give isl_union_map *subtree_schedule_extend(
	__isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer)
{
	isl_multi_union_pw_aff *mupa;
	isl_union_map *umap;
	isl_union_set *domain;
	isl_size n;

	if (!tree)
		return NULL;

	switch (tree->type) {
	case isl_schedule_node_error:
		return isl_union_map_free(outer);
	case isl_schedule_node_extension:
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"cannot construct subtree schedule of tree "
			"with extension nodes",
			return isl_union_map_free(outer));
	case isl_schedule_node_context:
	case isl_schedule_node_guard:
	case isl_schedule_node_mark:
		return subtree_schedule_extend_child(tree, outer);
	case isl_schedule_node_band:
		n = isl_schedule_tree_band_n_member(tree);
		if (n < 0)
			return isl_union_map_free(outer);
		if (n == 0)
			return subtree_schedule_extend_child(tree, outer);
		mupa = isl_schedule_band_get_partial_schedule(tree->band);
		umap = isl_union_map_from_multi_union_pw_aff(mupa);
		outer = isl_union_map_flat_range_product(outer, umap);
		umap = subtree_schedule_extend_child(tree, outer);
		break;
	case isl_schedule_node_domain:
		domain = isl_schedule_tree_domain_get_domain(tree);
		umap = isl_union_map_from_domain(domain);
		outer = isl_union_map_flat_range_product(outer, umap);
		umap = subtree_schedule_extend_child(tree, outer);
		break;
	case isl_schedule_node_expansion:
		umap = isl_schedule_tree_expansion_get_expansion(tree);
		outer = isl_union_map_apply_domain(outer, umap);
		umap = subtree_schedule_extend_child(tree, outer);
		break;
	case isl_schedule_node_filter:
		domain = isl_schedule_tree_filter_get_filter(tree);
		umap = isl_union_map_from_domain(domain);
		outer = isl_union_map_flat_range_product(outer, umap);
		umap = subtree_schedule_extend_child(tree, outer);
		break;
	case isl_schedule_node_leaf:
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
			"leaf node should be handled by caller", return NULL);
	case isl_schedule_node_set:
	case isl_schedule_node_sequence:
		umap = subtree_schedule_extend_from_children(tree, outer);
		break;
	}

	return umap;
}

static __isl_give isl_union_set *initial_domain(
	__isl_keep isl_schedule_tree *tree);

/* Extract a universe domain from the children of the tree root "tree",
 * which is a set or sequence, meaning that its children are filters.
 * In particular, return the union of the universes of the filters.
 */
static __isl_give isl_union_set *initial_domain_from_children(
	__isl_keep isl_schedule_tree *tree)
{
	int i;
	isl_size n;
	isl_space *space;
	isl_union_set *domain;

	n = isl_schedule_tree_n_children(tree);
	if (n < 0)
		return NULL;
	if (n == 0)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
			"missing children", return NULL);

	space = extract_space_from_filter_child(tree);
	domain = isl_union_set_empty(space);

	for (i = 0; i < n; ++i) {
		isl_schedule_tree *child;
		isl_union_set *domain_i;

		child = isl_schedule_tree_get_child(tree, i);
		domain_i = initial_domain(child);
		domain = isl_union_set_union(domain, domain_i);
		isl_schedule_tree_free(child);
	}

	return domain;
}

/* Extract a universe domain from the tree root "tree".
 * The caller is responsible for making sure that this node
 * would not be skipped by isl_schedule_tree_first_schedule_descendant
 * and that it is not a leaf node.
 */
static __isl_give isl_union_set *initial_domain(
	__isl_keep isl_schedule_tree *tree)
{
	isl_multi_union_pw_aff *mupa;
	isl_union_set *domain;
	isl_union_map *exp;
	isl_size n;

	if (!tree)
		return NULL;

	switch (tree->type) {
	case isl_schedule_node_error:
		return NULL;
	case isl_schedule_node_context:
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
			"context node should be handled by caller",
			return NULL);
	case isl_schedule_node_guard:
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
			"guard node should be handled by caller",
			return NULL);
	case isl_schedule_node_mark:
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
			"mark node should be handled by caller",
			return NULL);
	case isl_schedule_node_extension:
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"cannot construct subtree schedule of tree "
			"with extension nodes", return NULL);
	case isl_schedule_node_band:
		n = isl_schedule_tree_band_n_member(tree);
		if (n < 0)
			return NULL;
		if (n == 0)
			isl_die(isl_schedule_tree_get_ctx(tree),
				isl_error_internal,
				"0D band should be handled by caller",
				return NULL);
		mupa = isl_schedule_band_get_partial_schedule(tree->band);
		domain = isl_multi_union_pw_aff_domain(mupa);
		domain = isl_union_set_universe(domain);
		break;
	case isl_schedule_node_domain:
		domain = isl_schedule_tree_domain_get_domain(tree);
		domain = isl_union_set_universe(domain);
		break;
	case isl_schedule_node_expansion:
		exp = isl_schedule_tree_expansion_get_expansion(tree);
		exp = isl_union_map_universe(exp);
		domain = isl_union_map_domain(exp);
		break;
	case isl_schedule_node_filter:
		domain = isl_schedule_tree_filter_get_filter(tree);
		domain = isl_union_set_universe(domain);
		break;
	case isl_schedule_node_leaf:
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
			"leaf node should be handled by caller", return NULL);
	case isl_schedule_node_set:
	case isl_schedule_node_sequence:
		domain = initial_domain_from_children(tree);
		break;
	}

	return domain;
}

/* Return the subtree schedule of a node that contains some schedule
 * information, i.e., a node that would not be skipped by
 * isl_schedule_tree_first_schedule_descendant and that is not a leaf.
 *
 * If the tree contains any expansions, then the returned subtree
 * schedule is formulated in terms of the expanded domains.
 * The tree is not allowed to contain any extension nodes.
 *
 * We start with an initial zero-dimensional subtree schedule based
 * on the domain information in the root node and then extend it
 * based on the schedule information in the root node and its descendants.
 */
__isl_give isl_union_map *isl_schedule_tree_get_subtree_schedule_union_map(
	__isl_keep isl_schedule_tree *tree)
{
	isl_union_set *domain;
	isl_union_map *umap;

	domain = initial_domain(tree);
	umap = isl_union_map_from_domain(domain);
	return subtree_schedule_extend(tree, umap);
}

/* Multiply the partial schedule of the band root node of "tree"
 * with the factors in "mv".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_band_scale(
	__isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv)
{
	if (!tree || !mv)
		goto error;
	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", goto error);

	tree = isl_schedule_tree_cow(tree);
	if (!tree)
		goto error;

	tree->band = isl_schedule_band_scale(tree->band, mv);
	if (!tree->band)
		return isl_schedule_tree_free(tree);

	return tree;
error:
	isl_schedule_tree_free(tree);
	isl_multi_val_free(mv);
	return NULL;
}

/* Divide the partial schedule of the band root node of "tree"
 * by the factors in "mv".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_band_scale_down(
	__isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv)
{
	if (!tree || !mv)
		goto error;
	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", goto error);

	tree = isl_schedule_tree_cow(tree);
	if (!tree)
		goto error;

	tree->band = isl_schedule_band_scale_down(tree->band, mv);
	if (!tree->band)
		return isl_schedule_tree_free(tree);

	return tree;
error:
	isl_schedule_tree_free(tree);
	isl_multi_val_free(mv);
	return NULL;
}

/* Reduce the partial schedule of the band root node of "tree"
 * modulo the factors in "mv".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_band_mod(
	__isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv)
{
	if (!tree || !mv)
		goto error;
	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", goto error);

	tree = isl_schedule_tree_cow(tree);
	if (!tree)
		goto error;

	tree->band = isl_schedule_band_mod(tree->band, mv);
	if (!tree->band)
		return isl_schedule_tree_free(tree);

	return tree;
error:
	isl_schedule_tree_free(tree);
	isl_multi_val_free(mv);
	return NULL;
}

/* Shift the partial schedule of the band root node of "tree" by "shift".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_band_shift(
	__isl_take isl_schedule_tree *tree,
	__isl_take isl_multi_union_pw_aff *shift)
{
	if (!tree || !shift)
		goto error;
	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", goto error);

	tree = isl_schedule_tree_cow(tree);
	if (!tree)
		goto error;

	tree->band = isl_schedule_band_shift(tree->band, shift);
	if (!tree->band)
		return isl_schedule_tree_free(tree);

	return tree;
error:
	isl_schedule_tree_free(tree);
	isl_multi_union_pw_aff_free(shift);
	return NULL;
}

/* Given two trees with sequence roots, replace the child at position
 * "pos" of "tree" with the children of "child".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_sequence_splice(
	__isl_take isl_schedule_tree *tree, int pos,
	__isl_take isl_schedule_tree *child)
{
	isl_size n;
	isl_schedule_tree_list *list1, *list2;

	tree = isl_schedule_tree_cow(tree);
	if (!tree || !child)
		goto error;
	if (isl_schedule_tree_get_type(tree) != isl_schedule_node_sequence)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a sequence node", goto error);
	n = isl_schedule_tree_n_children(tree);
	if (n < 0)
		goto error;
	if (pos < 0 || pos >= n)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"position out of bounds", goto error);
	if (isl_schedule_tree_get_type(child) != isl_schedule_node_sequence)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a sequence node", goto error);

	list1 = isl_schedule_tree_list_copy(tree->children);
	list1 = isl_schedule_tree_list_drop(list1, pos, n - pos);
	list2 = isl_schedule_tree_list_copy(tree->children);
	list2 = isl_schedule_tree_list_drop(list2, 0, pos + 1);
	list1 = isl_schedule_tree_list_concat(list1,
				isl_schedule_tree_list_copy(child->children));
	list1 = isl_schedule_tree_list_concat(list1, list2);

	isl_schedule_tree_free(tree);
	isl_schedule_tree_free(child);
	return isl_schedule_tree_from_children(isl_schedule_node_sequence,
						list1);
error:
	isl_schedule_tree_free(tree);
	isl_schedule_tree_free(child);
	return NULL;
}

/* Tile the band root node of "tree" with tile sizes "sizes".
 *
 * We duplicate the band node, change the schedule of one of them
 * to the tile schedule and the other to the point schedule and then
 * attach the point band as a child to the tile band.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_band_tile(
	__isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *sizes)
{
	isl_schedule_tree *child = NULL;

	if (!tree || !sizes)
		goto error;
	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", goto error);

	child = isl_schedule_tree_copy(tree);
	tree = isl_schedule_tree_cow(tree);
	child = isl_schedule_tree_cow(child);
	if (!tree || !child)
		goto error;

	tree->band = isl_schedule_band_tile(tree->band,
					    isl_multi_val_copy(sizes));
	if (!tree->band)
		goto error;
	child->band = isl_schedule_band_point(child->band, tree->band, sizes);
	if (!child->band)
		child = isl_schedule_tree_free(child);

	tree = isl_schedule_tree_replace_child(tree, 0, child);

	return tree;
error:
	isl_schedule_tree_free(child);
	isl_schedule_tree_free(tree);
	isl_multi_val_free(sizes);
	return NULL;
}

/* Given an isolate AST generation option "isolate" for a band of size pos + n,
 * return the corresponding option for a band covering the first "pos"
 * members.
 *
 * The input isolate option is of the form
 *
 *	isolate[[flattened outer bands] -> [pos; n]]
 *
 * The output isolate option is of the form
 *
 *	isolate[[flattened outer bands] -> [pos]]
 */
static __isl_give isl_set *isolate_initial(__isl_keep isl_set *isolate,
	int pos, int n)
{
	isl_id *id;
	isl_map *map;

	isolate = isl_set_copy(isolate);
	id = isl_set_get_tuple_id(isolate);
	map = isl_set_unwrap(isolate);
	map = isl_map_project_out(map, isl_dim_out, pos, n);
	isolate = isl_map_wrap(map);
	isolate = isl_set_set_tuple_id(isolate, id);

	return isolate;
}

/* Given an isolate AST generation option "isolate" for a band of size pos + n,
 * return the corresponding option for a band covering the final "n"
 * members within a band covering the first "pos" members.
 *
 * The input isolate option is of the form
 *
 *	isolate[[flattened outer bands] -> [pos; n]]
 *
 * The output isolate option is of the form
 *
 *	isolate[[flattened outer bands; pos] -> [n]]
 *
 *
 * The range is first split into
 *
 *	isolate[[flattened outer bands] -> [[pos] -> [n]]]
 *
 * and then the first pos members are moved to the domain
 *
 *	isolate[[[flattened outer bands] -> [pos]] -> [n]]
 *
 * after which the domain is flattened to obtain the desired output.
 */
static __isl_give isl_set *isolate_final(__isl_keep isl_set *isolate,
	int pos, int n)
{
	isl_id *id;
	isl_space *space;
	isl_multi_aff *ma1, *ma2;
	isl_map *map;

	isolate = isl_set_copy(isolate);
	id = isl_set_get_tuple_id(isolate);
	map = isl_set_unwrap(isolate);
	space = isl_space_range(isl_map_get_space(map));
	ma1 = isl_multi_aff_project_out_map(isl_space_copy(space),
						   isl_dim_set, pos, n);
	ma2 = isl_multi_aff_project_out_map(space, isl_dim_set, 0, pos);
	ma1 = isl_multi_aff_range_product(ma1, ma2);
	map = isl_map_apply_range(map, isl_map_from_multi_aff(ma1));
	map = isl_map_uncurry(map);
	map = isl_map_flatten_domain(map);
	isolate = isl_map_wrap(map);
	isolate = isl_set_set_tuple_id(isolate, id);

	return isolate;
}

/* Split the band root node of "tree" into two nested band nodes,
 * one with the first "pos" dimensions and
 * one with the remaining dimensions.
 * The tree is itself positioned at schedule depth "depth".
 *
 * The loop AST generation type options and the isolate option
 * are split over the two band nodes.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_band_split(
	__isl_take isl_schedule_tree *tree, int pos, int depth)
{
	isl_size n;
	isl_set *isolate, *tree_isolate, *child_isolate;
	isl_schedule_tree *child;

	if (!tree)
		return NULL;
	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", return isl_schedule_tree_free(tree));

	n = isl_schedule_tree_band_n_member(tree);
	if (n < 0)
		return isl_schedule_tree_free(tree);
	if (pos < 0 || pos > n)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"position out of bounds",
			return isl_schedule_tree_free(tree));

	child = isl_schedule_tree_copy(tree);
	tree = isl_schedule_tree_cow(tree);
	child = isl_schedule_tree_cow(child);
	if (!tree || !child)
		goto error;

	isolate = isl_schedule_tree_band_get_ast_isolate_option(tree, depth);
	tree_isolate = isolate_initial(isolate, pos, n - pos);
	child_isolate = isolate_final(isolate, pos, n - pos);
	child->band = isl_schedule_band_drop(child->band, 0, pos);
	child->band = isl_schedule_band_replace_ast_build_option(child->band,
					isl_set_copy(isolate), child_isolate);
	tree->band = isl_schedule_band_drop(tree->band, pos, n - pos);
	tree->band = isl_schedule_band_replace_ast_build_option(tree->band,
					isl_set_copy(isolate), tree_isolate);
	isl_set_free(isolate);
	if (!child->band || !tree->band)
		goto error;

	tree = isl_schedule_tree_replace_child(tree, 0, child);

	return tree;
error:
	isl_schedule_tree_free(child);
	isl_schedule_tree_free(tree);
	return NULL;
}

/* Attach "tree2" at each of the leaves of "tree1".
 *
 * If "tree1" does not have any explicit children, then make "tree2"
 * its single child.  Otherwise, attach "tree2" to the leaves of
 * each of the children of "tree1".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_append_to_leaves(
	__isl_take isl_schedule_tree *tree1,
	__isl_take isl_schedule_tree *tree2)
{
	int i;
	isl_size n;

	n = isl_schedule_tree_n_children(tree1);
	if (n < 0 || !tree2)
		goto error;
	if (n == 0) {
		isl_schedule_tree_list *list;
		list = isl_schedule_tree_list_from_schedule_tree(tree2);
		tree1 = isl_schedule_tree_set_children(tree1, list);
		return tree1;
	}
	for (i = 0; i < n; ++i) {
		isl_schedule_tree *child;

		child = isl_schedule_tree_get_child(tree1, i);
		child = isl_schedule_tree_append_to_leaves(child,
					isl_schedule_tree_copy(tree2));
		tree1 = isl_schedule_tree_replace_child(tree1, i, child);
	}

	isl_schedule_tree_free(tree2);
	return tree1;
error:
	isl_schedule_tree_free(tree1);
	isl_schedule_tree_free(tree2);
	return NULL;
}

/* Reset the user pointer on all identifiers of parameters and tuples
 * in the root of "tree".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_reset_user(
	__isl_take isl_schedule_tree *tree)
{
	if (isl_schedule_tree_is_leaf(tree))
		return tree;

	tree = isl_schedule_tree_cow(tree);
	if (!tree)
		return NULL;

	switch (tree->type) {
	case isl_schedule_node_error:
		return isl_schedule_tree_free(tree);
	case isl_schedule_node_band:
		tree->band = isl_schedule_band_reset_user(tree->band);
		if (!tree->band)
			return isl_schedule_tree_free(tree);
		break;
	case isl_schedule_node_context:
		tree->context = isl_set_reset_user(tree->context);
		if (!tree->context)
			return isl_schedule_tree_free(tree);
		break;
	case isl_schedule_node_domain:
		tree->domain = isl_union_set_reset_user(tree->domain);
		if (!tree->domain)
			return isl_schedule_tree_free(tree);
		break;
	case isl_schedule_node_expansion:
		tree->contraction =
			isl_union_pw_multi_aff_reset_user(tree->contraction);
		tree->expansion = isl_union_map_reset_user(tree->expansion);
		if (!tree->contraction || !tree->expansion)
			return isl_schedule_tree_free(tree);
		break;
	case isl_schedule_node_extension:
		tree->extension = isl_union_map_reset_user(tree->extension);
		if (!tree->extension)
			return isl_schedule_tree_free(tree);
		break;
	case isl_schedule_node_filter:
		tree->filter = isl_union_set_reset_user(tree->filter);
		if (!tree->filter)
			return isl_schedule_tree_free(tree);
		break;
	case isl_schedule_node_guard:
		tree->guard = isl_set_reset_user(tree->guard);
		if (!tree->guard)
			return isl_schedule_tree_free(tree);
		break;
	case isl_schedule_node_leaf:
	case isl_schedule_node_mark:
	case isl_schedule_node_sequence:
	case isl_schedule_node_set:
		break;
	}

	return tree;
}

/* Align the parameters of the root of "tree" to those of "space".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_align_params(
	__isl_take isl_schedule_tree *tree, __isl_take isl_space *space)
{
	if (!space)
		goto error;

	if (isl_schedule_tree_is_leaf(tree)) {
		isl_space_free(space);
		return tree;
	}

	tree = isl_schedule_tree_cow(tree);
	if (!tree)
		goto error;

	switch (tree->type) {
	case isl_schedule_node_error:
		goto error;
	case isl_schedule_node_band:
		tree->band = isl_schedule_band_align_params(tree->band, space);
		if (!tree->band)
			return isl_schedule_tree_free(tree);
		break;
	case isl_schedule_node_context:
		tree->context = isl_set_align_params(tree->context, space);
		if (!tree->context)
			return isl_schedule_tree_free(tree);
		break;
	case isl_schedule_node_domain:
		tree->domain = isl_union_set_align_params(tree->domain, space);
		if (!tree->domain)
			return isl_schedule_tree_free(tree);
		break;
	case isl_schedule_node_expansion:
		tree->contraction =
			isl_union_pw_multi_aff_align_params(tree->contraction,
							isl_space_copy(space));
		tree->expansion = isl_union_map_align_params(tree->expansion,
								space);
		if (!tree->contraction || !tree->expansion)
			return isl_schedule_tree_free(tree);
		break;
	case isl_schedule_node_extension:
		tree->extension = isl_union_map_align_params(tree->extension,
								space);
		if (!tree->extension)
			return isl_schedule_tree_free(tree);
		break;
	case isl_schedule_node_filter:
		tree->filter = isl_union_set_align_params(tree->filter, space);
		if (!tree->filter)
			return isl_schedule_tree_free(tree);
		break;
	case isl_schedule_node_guard:
		tree->guard = isl_set_align_params(tree->guard, space);
		if (!tree->guard)
			return isl_schedule_tree_free(tree);
		break;
	case isl_schedule_node_leaf:
	case isl_schedule_node_mark:
	case isl_schedule_node_sequence:
	case isl_schedule_node_set:
		isl_space_free(space);
		break;
	}

	return tree;
error:
	isl_space_free(space);
	isl_schedule_tree_free(tree);
	return NULL;
}

/* Does "tree" involve the iteration domain?
 * That is, does it need to be modified
 * by isl_schedule_tree_pullback_union_pw_multi_aff?
 */
static int involves_iteration_domain(__isl_keep isl_schedule_tree *tree)
{
	if (!tree)
		return -1;

	switch (tree->type) {
	case isl_schedule_node_error:
		return -1;
	case isl_schedule_node_band:
	case isl_schedule_node_domain:
	case isl_schedule_node_expansion:
	case isl_schedule_node_extension:
	case isl_schedule_node_filter:
		return 1;
	case isl_schedule_node_context:
	case isl_schedule_node_leaf:
	case isl_schedule_node_guard:
	case isl_schedule_node_mark:
	case isl_schedule_node_sequence:
	case isl_schedule_node_set:
		return 0;
	}

	isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
		"unhandled case", return -1);
}

/* Compute the pullback of the root node of "tree" by the function
 * represented by "upma".
 * In other words, plug in "upma" in the iteration domains of
 * the root node of "tree".
 * We currently do not handle expansion nodes.
 *
 * We first check if the root node involves any iteration domains.
 * If so, we handle the specific cases.
 */
__isl_give isl_schedule_tree *isl_schedule_tree_pullback_union_pw_multi_aff(
	__isl_take isl_schedule_tree *tree,
	__isl_take isl_union_pw_multi_aff *upma)
{
	int involves;

	if (!tree || !upma)
		goto error;

	involves = involves_iteration_domain(tree);
	if (involves < 0)
		goto error;
	if (!involves) {
		isl_union_pw_multi_aff_free(upma);
		return tree;
	}

	tree = isl_schedule_tree_cow(tree);
	if (!tree)
		goto error;

	if (tree->type == isl_schedule_node_band) {
		tree->band = isl_schedule_band_pullback_union_pw_multi_aff(
							    tree->band, upma);
		if (!tree->band)
			return isl_schedule_tree_free(tree);
	} else if (tree->type == isl_schedule_node_domain) {
		tree->domain =
			isl_union_set_preimage_union_pw_multi_aff(tree->domain,
									upma);
		if (!tree->domain)
			return isl_schedule_tree_free(tree);
	} else if (tree->type == isl_schedule_node_expansion) {
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_unsupported,
			"cannot pullback expansion node", goto error);
	} else if (tree->type == isl_schedule_node_extension) {
		tree->extension =
			isl_union_map_preimage_range_union_pw_multi_aff(
			    tree->extension, upma);
		if (!tree->extension)
			return isl_schedule_tree_free(tree);
	} else if (tree->type == isl_schedule_node_filter) {
		tree->filter =
			isl_union_set_preimage_union_pw_multi_aff(tree->filter,
									upma);
		if (!tree->filter)
			return isl_schedule_tree_free(tree);
	}

	return tree;
error:
	isl_union_pw_multi_aff_free(upma);
	isl_schedule_tree_free(tree);
	return NULL;
}

/* Compute the gist of the band tree root with respect to "context".
 */
__isl_give isl_schedule_tree *isl_schedule_tree_band_gist(
	__isl_take isl_schedule_tree *tree, __isl_take isl_union_set *context)
{
	if (!tree)
		return NULL;
	if (tree->type != isl_schedule_node_band)
		isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
			"not a band node", goto error);
	tree = isl_schedule_tree_cow(tree);
	if (!tree)
		goto error;

	tree->band = isl_schedule_band_gist(tree->band, context);
	if (!tree->band)
		return isl_schedule_tree_free(tree);
	return tree;
error:
	isl_union_set_free(context);
	isl_schedule_tree_free(tree);
	return NULL;
}

/* Are any members in "band" marked coincident?
 */
static isl_bool any_coincident(__isl_keep isl_schedule_band *band)
{
	int i;
	isl_size n;

	n = isl_schedule_band_n_member(band);
	if (n < 0)
		return isl_bool_error;
	for (i = 0; i < n; ++i) {
		isl_bool coincident;

		coincident = isl_schedule_band_member_get_coincident(band, i);
		if (coincident < 0 || coincident)
			return coincident;
	}

	return isl_bool_false;
}

/* Print the band node "band" to "p".
 *
 * The permutable and coincident properties are only printed if they
 * are different from the defaults.
 * The coincident property is always printed in YAML flow style.
 */
static __isl_give isl_printer *print_tree_band(__isl_take isl_printer *p,
	__isl_keep isl_schedule_band *band)
{
	isl_union_set *options;
	isl_bool empty;
	isl_bool coincident;

	p = isl_printer_print_str(p, "schedule");
	p = isl_printer_yaml_next(p);
	p = isl_printer_print_str(p, "\"");
	p = isl_printer_print_multi_union_pw_aff(p, band->mupa);
	p = isl_printer_print_str(p, "\"");
	if (isl_schedule_band_get_permutable(band)) {
		p = isl_printer_yaml_next(p);
		p = isl_printer_print_str(p, "permutable");
		p = isl_printer_yaml_next(p);
		p = isl_printer_print_int(p, 1);
	}
	coincident = any_coincident(band);
	if (coincident < 0)
		return isl_printer_free(p);
	if (coincident) {
		int i;
		isl_size n;
		int style;

		p = isl_printer_yaml_next(p);
		p = isl_printer_print_str(p, "coincident");
		p = isl_printer_yaml_next(p);
		style = isl_printer_get_yaml_style(p);
		p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_FLOW);
		p = isl_printer_yaml_start_sequence(p);
		n = isl_schedule_band_n_member(band);
		if (n < 0)
			return isl_printer_free(p);
		for (i = 0; i < n; ++i) {
			p = isl_printer_print_int(p,
			    isl_schedule_band_member_get_coincident(band, i));
			p = isl_printer_yaml_next(p);
		}
		p = isl_printer_yaml_end_sequence(p);
		p = isl_printer_set_yaml_style(p, style);
	}
	options = isl_schedule_band_get_ast_build_options(band);
	empty = isl_union_set_is_empty(options);
	if (empty < 0)
		p = isl_printer_free(p);
	if (!empty) {
		p = isl_printer_yaml_next(p);
		p = isl_printer_print_str(p, "options");
		p = isl_printer_yaml_next(p);
		p = isl_printer_print_str(p, "\"");
		p = isl_printer_print_union_set(p, options);
		p = isl_printer_print_str(p, "\"");
	}
	isl_union_set_free(options);

	return p;
}

#undef BASE
#define BASE str
#define isl_str const char
#include "print_yaml_field_templ.c"

#undef BASE
#define BASE set
#include "print_yaml_field_templ.c"

#undef BASE
#define BASE union_set
#include "print_yaml_field_templ.c"

#undef BASE
#define BASE union_map
#include "print_yaml_field_templ.c"

#undef BASE
#define BASE union_pw_multi_aff
#include "print_yaml_field_templ.c"

/* Print "tree" to "p".
 *
 * If "n_ancestor" is non-negative, then "child_pos" contains the child
 * positions of a descendant of the current node that should be marked
 * (by the comment "YOU ARE HERE").  In particular, if "n_ancestor"
 * is zero, then the current node should be marked.
 * The marking is only printed in YAML block format.
 *
 * Implicit leaf nodes are not printed, except if they correspond
 * to the node that should be marked.
 */
__isl_give isl_printer *isl_printer_print_schedule_tree_mark(
	__isl_take isl_printer *p, __isl_keep isl_schedule_tree *tree,
	int n_ancestor, int *child_pos)
{
	int i;
	isl_size n;
	int sequence = 0;
	int block;

	block = isl_printer_get_yaml_style(p) == ISL_YAML_STYLE_BLOCK;

	p = isl_printer_yaml_start_mapping(p);
	if (n_ancestor == 0 && block) {
		p = isl_printer_print_str(p, "# YOU ARE HERE");
		p = isl_printer_end_line(p);
		p = isl_printer_start_line(p);
	}
	switch (tree->type) {
	case isl_schedule_node_error:
		p = isl_printer_print_str(p, "ERROR");
		p = isl_printer_yaml_next(p);
		break;
	case isl_schedule_node_leaf:
		p = isl_printer_print_str(p, "leaf");
		p = isl_printer_yaml_next(p);
		break;
	case isl_schedule_node_sequence:
		p = isl_printer_print_str(p, "sequence");
		p = isl_printer_yaml_next(p);
		sequence = 1;
		break;
	case isl_schedule_node_set:
		p = isl_printer_print_str(p, "set");
		p = isl_printer_yaml_next(p);
		sequence = 1;
		break;
	case isl_schedule_node_context:
		p = print_yaml_field_set(p, "context", tree->context);
		break;
	case isl_schedule_node_domain:
		p = print_yaml_field_union_set(p, "domain", tree->domain);
		break;
	case isl_schedule_node_expansion:
		p = print_yaml_field_union_pw_multi_aff(p, "contraction",
							tree->contraction);
		p = print_yaml_field_union_map(p, "expansion", tree->expansion);
		break;
	case isl_schedule_node_extension:
		p = print_yaml_field_union_map(p, "extension", tree->extension);
		break;
	case isl_schedule_node_filter:
		p = print_yaml_field_union_set(p, "filter", tree->filter);
		break;
	case isl_schedule_node_guard:
		p = print_yaml_field_set(p, "guard", tree->guard);
		break;
	case isl_schedule_node_mark:
		p = print_yaml_field_str(p, "mark",
					isl_id_get_name(tree->mark));
		break;
	case isl_schedule_node_band:
		p = print_tree_band(p, tree->band);
		p = isl_printer_yaml_next(p);
		break;
	}

	n = isl_schedule_tree_n_children(tree);
	if (n < 0)
		return isl_printer_free(p);
	if (n == 0) {
		if (n_ancestor > 0 && block) {
			isl_schedule_tree *leaf;

			p = isl_printer_print_str(p, "child");
			p = isl_printer_yaml_next(p);
			leaf = isl_schedule_tree_leaf(isl_printer_get_ctx(p));
			p = isl_printer_print_schedule_tree_mark(p,
					leaf, 0, NULL);
			isl_schedule_tree_free(leaf);
			p = isl_printer_yaml_next(p);
		}
		return isl_printer_yaml_end_mapping(p);
	}

	if (sequence) {
		p = isl_printer_yaml_start_sequence(p);
	} else {
		p = isl_printer_print_str(p, "child");
		p = isl_printer_yaml_next(p);
	}

	for (i = 0; i < n; ++i) {
		isl_schedule_tree *t;

		t = isl_schedule_tree_get_child(tree, i);
		if (n_ancestor > 0 && child_pos[0] == i)
			p = isl_printer_print_schedule_tree_mark(p, t,
						n_ancestor - 1, child_pos + 1);
		else
			p = isl_printer_print_schedule_tree_mark(p, t,
						-1, NULL);
		isl_schedule_tree_free(t);

		p = isl_printer_yaml_next(p);
	}

	if (sequence)
		p = isl_printer_yaml_end_sequence(p);
	p = isl_printer_yaml_end_mapping(p);

	return p;
}

/* Print "tree" to "p".
 */
__isl_give isl_printer *isl_printer_print_schedule_tree(
	__isl_take isl_printer *p, __isl_keep isl_schedule_tree *tree)
{
	return isl_printer_print_schedule_tree_mark(p, tree, -1, NULL);
}

void isl_schedule_tree_dump(__isl_keep isl_schedule_tree *tree)
{
	isl_ctx *ctx;
	isl_printer *printer;

	if (!tree)
		return;

	ctx = isl_schedule_tree_get_ctx(tree);
	printer = isl_printer_to_file(ctx, stderr);
	printer = isl_printer_set_yaml_style(printer, ISL_YAML_STYLE_BLOCK);
	printer = isl_printer_print_schedule_tree(printer, tree);

	isl_printer_free(printer);
}


text:
*+CHREDT

       SUBROUTINE CHREDT (STATUS)
C      --------------------------
C
C  Checks current redtape for validity.
C
C  Returned:
C      STATUS    integer     status value
C
C  Checks the map redtape currently present in the run-time common blocks
C  for validity.  Checks are made on the map keyword and on the internal
C  data type.
C
C  The STATUS value should be zero on entry.  Possible error values are:
C
C      - invalid map redtape (ILL_REDTAPE)
C      - invalid internal data type (ILL_DATYPE)
C
C  (DJT, 24 November 87)
C
*-
       INTEGER  STATUS
C
       include '/mrao/include/maplib_redtape.inc'
       include '/mrao/include/maplib_errors.inc'
C
       IF (STATUS.NE.0) RETURN
C
C  Check the first page of redtape
C
       IF (RTHDR.NE.'MAP' .AND. RTHDR.NE.'APERTURE') THEN
         STATUS=ILL_REDTAPE
       ELSEIF ((RTHDR.EQ.'MAP' .AND. ISWD.GT.3) .OR.
     :         (RTHDR.EQ.'APERTURE' .AND. ISWD.NE.4)) THEN
         STATUS=ILL_DATYPE
       ENDIF
C
       END

redpajama_set_name: RedPajamaGithub


text:
#include <aws/ec2/model/DatafeedSubscriptionState.h>
#include <aws/core/utils/HashingUtils.h>
#include <aws/core/Globals.h>
#include <aws/core/utils/EnumParseOverflowContainer.h>

using namespace Aws::Utils;

namespace Aws
{
  namespace EC2
  {
    namespace Model
    {
      namespace DatafeedSubscriptionStateMapper
      {

        static const int Active_HASH = HashingUtils::HashString("Active");
        static const int Inactive_HASH = HashingUtils::HashString("Inactive");

        DatafeedSubscriptionState GetDatafeedSubscriptionStateForName(const Aws::String& name)
        {
          int hashCode = HashingUtils::HashString(name.c_str());
          if (hashCode == Active_HASH)
          {
            return DatafeedSubscriptionState::Active;
          }
          else if (hashCode == Inactive_HASH)
          {
            return DatafeedSubscriptionState::Inactive;
          }
          EnumParseOverflowContainer* overflowContainer = Aws::GetEnumOverflowContainer();
          if(overflowContainer)
          {
            overflowContainer->StoreOverflow(hashCode, name);
            return static_cast<DatafeedSubscriptionState>(hashCode);
          }

          return DatafeedSubscriptionState::NOT_SET;
        }

        Aws::String GetNameForDatafeedSubscriptionState(DatafeedSubscriptionState enumValue)
        {
          switch(enumValue)
          {
          case DatafeedSubscriptionState::Active:
            return "Active";
          case DatafeedSubscriptionState::Inactive:
            return "Inactive";
          default:
            EnumParseOverflowContainer* overflowContainer = Aws::GetEnumOverflowContainer();
            if(overflowContainer)
            {
              return overflowContainer->RetrieveOverflow(static_cast<int>(enumValue));
            }

            return {};
          }
        }

      } // namespace DatafeedSubscriptionStateMapper
    } // namespace Model
  } // namespace EC2
} // namespace Aws


text:
powow.info Terms of Service

1. Terms

By accessing the website and app at http://powow.info, you are agreeing to be bound
    by these terms of service, all applicable laws and regulations, and agree that you are responsible for compliance
    with any applicable local laws. If you do not agree with any of these terms, you are prohibited from using or
    accessing this site. The materials contained in this website are protected by applicable copyright and trademark
    law.

2. Use License

        Permission is granted to temporarily download one copy of the materials (information or software) on
        powow.info's website for personal, non-commercial transitory viewing only. This is the grant of a license, not a
        transfer of title, and under this license you may not:

modify or copy the materials;

use the materials for any commercial purpose, or for any public display (commercial or
                non-commercial);

attempt to decompile or reverse engineer any software contained on powow.info's website;

remove any copyright or other proprietary notations from the materials; or

transfer the materials to another person or "mirror" the materials on any other server.

content posted will not contain any objectionable content, including but not limited to porn, religious
                abuse, sexual abuse etc.

This license shall automatically terminate if you violate any of these restrictions and may be terminated by
        powow.info at any time.

3. Disclaimer

The materials on powow.info's website are provided on an 'as is' basis. powow.info makes no warranties,
        expressed or implied, and hereby disclaims and negates all other warranties including, without limitation,
        implied warranties or conditions of merchantability, fitness for a particular purpose, or non-infringement of
        intellectual property or other violation of rights.

Further, powow.info does not warrant or make any representations concerning the accuracy, likely results, or
        reliability of the use of the materials on its website or otherwise relating to such materials or on any sites
        linked to this site.

4. Limitations

In no event shall powow.info or its suppliers be liable for any damages (including, without limitation, damages for
    loss of data or profit, or due to business interruption) arising out of the use or inability to use the materials on
    powow.info's website, even if powow.info or a powow.info authorized representative has been notified orally or in
    writing of the possibility of such damage. Because some jurisdictions do not allow limitations on implied
    warranties, or limitations of liability for consequential or incidental damages, these limitations may not apply to
    you.

5. Accuracy of materials

The materials appearing on powow.info's website could include technical, typographical, or photographic errors.
    powow.info does not warrant that any of the materials on its website are accurate, complete or current. powow.info
    may make changes to the materials contained on its website at any time without notice. However powow.info does not
    make any commitment to update the materials.

6. Links

powow.info has not reviewed all of the sites linked to its website and is not responsible for the contents of any
    such linked site. The inclusion of any link does not imply endorsement by powow.info of the site. Use of any such
    linked website is at the user's own risk.

7. Modifications

powow.info may revise these terms of service for its website at any time without notice. By using this website you
    are agreeing to be bound by the then current version of these terms of service.

8. Governing Law

These terms and conditions are governed by and construed in accordance with the laws of Almere, Netherlands and you
    irrevocably submit to the exclusive jurisdiction of the courts in that State or location.

Privacy Policy

Your privacy is important to us.

It is powow.info's policy to respect your privacy regarding any information we may collect while operating our
    website. Accordingly, we have developed this privacy policy in order for you to understand how we collect, use,
    communicate, disclose and otherwise make use of personal information. We have outlined our privacy policy below.

We will collect personal information by lawful and fair means and, where appropriate, with the knowledge or
        consent of the individual concerned.

In order to use powow services, we collect user data, if at all it is available for other to use an approximate
        user location will be provided

Before or at the time of collecting personal information, we will identify the purposes for which information is
        being collected.

We will collect and use personal information solely for fulfilling those purposes specified by us and for other
        ancillary purposes, unless we obtain the consent of the individual concerned or as required by law.

Personal data should be relevant to the purposes for which it is to be used, and, to the extent necessary for
        those purposes, should be accurate, complete, and up-to-date.

We will protect personal information by using reasonable security safeguards against loss or theft, as well as
        unauthorized access, disclosure, copying, use or modification.

We will make readily available to customers information about our policies and practices relating to the
        management of personal information.

We will only retain personal information for as long as necessary for the fulfilment of those purposes.

We are committed to conducting our business in accordance with these principles in order to ensure that the
    confidentiality of personal information is protected and maintained. powow.info may change this privacy policy from
    time to time at powow.info's sole discretion.


text:
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
    <data>
        <record id="product_product_tree_view_image" model="ir.ui.view">
            <field name="name">product.product.tree</field>
            <field name="model">product.product</field>
            <field name="inherit_id" ref="product.product_template_tree_view"/>
            <field name="arch" type="xml">
                <field name="name" position="before">
                    <field name="image_small" widget="image" height="64" class="oe_avatar"/>
                </field>
            </field>
        </record>
    </data>
</openerp>


text:
<?php

use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;

class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
            new Symfony\Bundle\SecurityBundle\SecurityBundle(),
            new Symfony\Bundle\TwigBundle\TwigBundle(),
            new Symfony\Bundle\MonologBundle\MonologBundle(),
            new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
            new Symfony\Bundle\AsseticBundle\AsseticBundle(),
            new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
            new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
            new Hte\SiteBundle\HteSiteBundle(),
            new Hte\AssetBundle\HteAssetBundle()
        );

        if (in_array($this->getEnvironment(), array('dev', 'test'))) {
            $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
            $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
            $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
        }

        return $bundles;
    }

    public function registerContainerConfiguration(LoaderInterface $loader)
    {
        $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');
    }
}


text:
package me.freets.freetsandroid.activity;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.widget.SwipeRefreshLayout;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;

import com.example.android.swipedismiss.SwipeDismissListViewTouchListener;

import me.freets.freetsandroid.R;
import me.freets.freetsandroid.adapter.EventListAdapter;

public class EventActivity extends Activity {

    private ListView mListView;
    private EventListAdapter mAdapter;

    private Menu menu;
    private MenuItem mToggleNotify;
    public static boolean notifyOn;

    private SwipeRefreshLayout mRefresher;

    //private RecyclerView mRecyclerView;
    //private EventAdapter mAdapter;
    //private RecyclerView.LayoutManager mLayoutManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_event);

        final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);

        mListView = (ListView)findViewById(R.id.event_list_view);
        mAdapter = new EventListAdapter(EventActivity.this, sharedPref);

        mListView.setAdapter(mAdapter);

        // Create a ListView-specific touch listener. ListViews are given special treatment because
        // by default they handle touches for their list items... i.e. they're in charge of drawing
        // the pressed state (the list selector), handling list item clicks, etc.
        SwipeDismissListViewTouchListener touchListener =
                new SwipeDismissListViewTouchListener(
                        mListView,
                        new SwipeDismissListViewTouchListener.DismissCallbacks() {
                            @Override
                            public boolean canDismiss(int position) {
                                return true;
                            }

                            @Override
                            public void onDismiss(ListView listView, int[] reverseSortedPositions) {
                                for (int position : reverseSortedPositions) {
                                    mAdapter.remove(mAdapter.getItem(position));
                                }
                                mAdapter.notifyDataSetChanged();
                            }
                        });
        mListView.setOnTouchListener(touchListener);
        // Setting this scroll listener is required to ensure that during ListView scrolling,
        // we don't look for swipes.
        mListView.setOnScrollListener(touchListener.makeScrollListener());

        //final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
        sharedPref.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener() {
            @Override
            public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
                if(key.equals("pref_notify") && mToggleNotify != null) {
                    if(sharedPref.getBoolean("pref_notify", true)) {
                        mToggleNotify.setIcon(R.drawable.ic_sync_white_36dp);
                    } else {
                        mToggleNotify.setIcon(R.drawable.ic_sync_disabled_white_36dp);
                    }
                }
            }
        });

        mRefresher = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
        mRefresher.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                mAdapter.get();
                mRefresher.setRefreshing(false);
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_event, menu);
        mToggleNotify = menu.findItem(R.id.action_enable_notify);

        final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
        if(sharedPref.getBoolean("pref_notify", true)) {
            mToggleNotify.setIcon(R.drawable.ic_sync_white_36dp);
        } else {
            mToggleNotify.setIcon(R.drawable.ic_sync_disabled_white_36dp);
        }

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        switch(id) {
            case R.id.action_settings:
                Intent settings = new Intent(this, SettingsActivity.class);
                startActivity(settings);
                return true;
            case R.id.action_enable_notify:
                return true;
        }

        return super.onOptionsItemSelected(item);
    }
}


text:
import test from 'ava';
import html from './helpers/html';
import { getOEmbedParameters, getOEmbedData, createEmbed, initializeEmbeds, resizeEmbeds, initAppendVideoMetadata } from '../src/lib/embed';

test('getOEmbedParameters retrieves the params from data attributes', (t) => {
    const el = html`<div data-vimeo-id="445351154" data-vimeo-width="640" data-vimeo-autoplay></div>`;
    t.deepEqual(getOEmbedParameters(el), {
        id: '445351154',
        width: '640',
        autoplay: 1
    });
});

test('getOEmbedParameters builds off of a defaults object', (t) => {
    const el = html`<div data-vimeo-id="445351154" data-vimeo-width="640" data-vimeo-autoplay></div>`;
    t.deepEqual(getOEmbedParameters(el, { loop: true }), {
        id: '445351154',
        width: '640',
        autoplay: 1,
        loop: true
    });
});

test('getOEmbedData doesn't operate on non-Vimeo urls', async (t) => {
    t.plan(1);
    await t.throwsAsync(() => getOEmbedData('https://notvimeo.com'), { instanceOf: TypeError });
});

test('getOEmbedData returns a json oembed response', async (t) => {
    t.plan(2);
    const result = await getOEmbedData('https://player.vimeo.com/video/445351154');
    t.is(typeof result, 'object');
    t.is(result.type, 'video');
});

test('createEmbed should throw if there's no element', (t) => {
    t.throws(() => {
        createEmbed({ html: 'html' });
    }, { instanceOf: TypeError });
});

test('createEmbed returns the already-initialized iframe', (t) => {
    const container = html`<div data-vimeo-initialized></div>`;
    const iframe = html`<iframe src="https://player.vimeo.com/445351154"></iframe>`;
    container.appendChild(iframe);
    t.deepEqual(createEmbed({ html: 'html' }, container), iframe);
});

test('createEmbed makes an iframe from the oembed data', (t) => {
    const container = html`<div></div>`;
    const markup = '';

    const embed = createEmbed({ html: markup }, container);
    t.true(container.getAttribute('data-vimeo-initialized') === 'true');
    t.deepEqual(embed.outerHTML, html`<iframe src="https://player.vimeo.com/445351154"></iframe>`.outerHTML);
});

test('createEmbed returns the iframe from a responsive embed', (t) => {
    const container = html`<div></div>`;
    const markup = '

';

    const embed = createEmbed({ html: markup }, container);
    t.true(container.getAttribute('data-vimeo-initialized') === 'true');
    t.deepEqual(embed.outerHTML, html`<iframe src="https://player.vimeo.com/video/445351154" style="position:absolute;top:0;left:0;width:100%;height:100%" frameborder="0"></iframe>`.outerHTML);
});

test('initializeEmbeds should create embeds', async (t) => {
    const div = html`<div data-vimeo-id="445351154" data-vimeo-width="640" id="handstick"></div>`;
    document.body.appendChild(div);

    await new Promise((resolve, reject) => {
        initializeEmbeds();
        // wait 500ms for the embeds to initialize.
        setTimeout(resolve, 500);
    });

    t.is(document.body.querySelector('#handstick').firstChild.nodeName, 'IFRAME');
});

test('resizeEmbeds is a function and sets a window property', (t) => {
    t.plan(2);
    t.true(typeof resizeEmbeds === 'function');

    resizeEmbeds();
    t.true(window.VimeoPlayerResizeEmbeds_);
});

test('initAppendVideoMetadata is a function and sets a window property', (t) => {
    t.plan(2);
    t.true(typeof initAppendVideoMetadata === 'function');

    initAppendVideoMetadata();
    t.true(window.VimeoSeoMetadataAppended);
});