package org.matheclipse.core.builtin.function;

import org.matheclipse.core.eval.EvalEngine;
import org.matheclipse.core.eval.exception.Validate;
import org.matheclipse.core.eval.interfaces.AbstractCoreFunctionEvaluator;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.generic.Functors;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.ISymbol;
import org.matheclipse.core.patternmatching.PatternMatcher;
import org.matheclipse.core.visit.VisitorLevelSpecification;

import com.google.common.base.Function;

public class Cases extends AbstractCoreFunctionEvaluator {
	private static class CasesPatternMatcherFunctor implements Function {
		protected final PatternMatcher matcher;
		protected IAST resultCollection;

		public CasesPatternMatcherFunctor(final PatternMatcher matcher, IAST resultCollection) {
			this.matcher = matcher;
			this.resultCollection = resultCollection;
		}

		@Override
		public IExpr apply(final IExpr arg) {
			if (arg.isAST()) {
				IAST ast = (IAST) arg;
				ast.filter(resultCollection, matcher);
			}
			return null;
		}

	}

	private static class CasesRulesFunctor implements Function {
		protected final Function function;
		protected IAST resultCollection;

		public CasesRulesFunctor(final Function function, IAST resultCollection) {
			this.function = function;
			this.resultCollection = resultCollection;
		}

		@Override
		public IExpr apply(final IExpr arg) {
			if (arg.isAST()) {
				IAST ast = (IAST) arg;
				IAST[] results = ast.split(function);
				resultCollection.addAll(results[0]);
			}
			return null;
		}

	}

	public Cases() {
	}

	@Override
	public IExpr evaluate(final IAST ast) {
		Validate.checkRange(ast, 3, 4);
		final EvalEngine engine = EvalEngine.get();
		final IExpr arg1 = engine.evaluate(ast.arg1());
		if (arg1.isAST()) {
			if (ast.size() == 4) {

				IAST result = F.List();
				if (ast.arg2().isRuleAST()) {
					Function function = Functors.rules((IAST) ast.arg2());
					CasesRulesFunctor crf = new CasesRulesFunctor(function, result);
					VisitorLevelSpecification level = new VisitorLevelSpecification(crf, ast.get(3), false);
					ast.arg1().accept(level);
					return result;
				}

				final PatternMatcher matcher = new PatternMatcher(ast.arg2());
				CasesPatternMatcherFunctor cpmf = new CasesPatternMatcherFunctor(matcher, result);
				VisitorLevelSpecification level = new VisitorLevelSpecification(cpmf, ast.get(3), false);
				ast.arg1().accept(level);
				return result;
			} else {
				return cases((IAST) ast.arg1(), ast.arg2());
			}
		}
		return null;
	}

	public static IAST cases(final IAST ast, final IExpr pattern) {
		if (pattern.isRuleAST()) {
			Function function = Functors.rules((IAST) pattern);
			IAST[] results = ast.split(function);
			return results[0];
		}
		final PatternMatcher matcher = new PatternMatcher(pattern);
		return ast.filter(ast.copyHead(), matcher);
	}

	@Override
	public void setUp(final ISymbol symbol) {
		symbol.setAttributes(ISymbol.HOLDALL);
	}

}

 

Ads help maintain this website.