mirror of
				https://github.com/DanilaFe/abacus
				synced 2025-10-31 01:43:41 -07:00 
			
		
		
		
	Merge pull request #39 from DanilaFe/more-kotlin
Switch more code to Kotlin
This commit is contained in:
		
						commit
						d7bb838866
					
				| @ -124,7 +124,7 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe | ||||
|      * @param matches the list of tokens from the source string. | ||||
|      * @return the construct tree expression. | ||||
|      */ | ||||
|     public TreeNode constructRecursive(List<Match<TokenType>> matches) { | ||||
|     public TreeNode constructRecursive(List<? extends Match<TokenType>> matches) { | ||||
|         if (matches.size() == 0) throw new ParseException("no tokens left in input"); | ||||
|         Match<TokenType> match = matches.remove(0); | ||||
|         TokenType matchType = match.getType(); | ||||
| @ -172,7 +172,7 @@ public class ShuntingYardParser implements Parser<Match<TokenType>>, PluginListe | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public TreeNode constructTree(List<Match<TokenType>> tokens) { | ||||
|     public TreeNode constructTree(List<? extends Match<TokenType>> tokens) { | ||||
|         if (tokens.isEmpty()) throw new ParseException("no input tokens"); | ||||
|         tokens = intoPostfix(new ArrayList<>(tokens)); | ||||
|         Collections.reverse(tokens); | ||||
|  | ||||
| @ -1,20 +0,0 @@ | ||||
| package org.nwapw.abacus.parsing; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| /** | ||||
|  * Interface that provides the ability to convert a string into a list of tokens. | ||||
|  * | ||||
|  * @param <T> the type of the tokens produced. | ||||
|  */ | ||||
| public interface Tokenizer<T> { | ||||
| 
 | ||||
|     /** | ||||
|      * Converts a string into tokens. | ||||
|      * | ||||
|      * @param string the string to convert. | ||||
|      * @return the list of tokens, or null on error. | ||||
|      */ | ||||
|     public List<T> tokenizeString(String string); | ||||
| 
 | ||||
| } | ||||
| @ -1,48 +0,0 @@ | ||||
| package org.nwapw.abacus.parsing; | ||||
| 
 | ||||
| import org.nwapw.abacus.tree.TreeNode; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| /** | ||||
|  * TreeBuilder class used to piece together a Tokenizer and | ||||
|  * Parser of the same kind. This is used to essentially avoid | ||||
|  * working with any parameters at all, and the generics | ||||
|  * in this class are used only to ensure the tokenizer and parser | ||||
|  * are of the same type. | ||||
|  * | ||||
|  * @param <T> the type of tokens created by the tokenizer and used by the parser. | ||||
|  */ | ||||
| public class TreeBuilder<T> { | ||||
| 
 | ||||
|     /** | ||||
|      * The tokenizer used to convert a string into tokens. | ||||
|      */ | ||||
|     private Tokenizer<T> tokenizer; | ||||
|     /** | ||||
|      * The parser used to parse a list of tokens into a tree. | ||||
|      */ | ||||
|     private Parser<T> parser; | ||||
| 
 | ||||
|     /** | ||||
|      * Create a new Tree Builder with the given tokenizer and parser | ||||
|      * | ||||
|      * @param tokenizer the tokenizer to turn strings into tokens | ||||
|      * @param parser    the parser to turn tokens into a tree | ||||
|      */ | ||||
|     public TreeBuilder(Tokenizer<T> tokenizer, Parser<T> parser) { | ||||
|         this.tokenizer = tokenizer; | ||||
|         this.parser = parser; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Parse the given string into a tree. | ||||
|      * | ||||
|      * @param input the string to parse into a tree. | ||||
|      * @return the resulting tree. | ||||
|      */ | ||||
|     public TreeNode fromString(String input) { | ||||
|         return parser.constructTree(tokenizer.tokenizeString(input)); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -1,12 +1,14 @@ | ||||
| package org.nwapw.abacus.plugin; | ||||
| package org.nwapw.abacus.plugin.standard; | ||||
| 
 | ||||
| import org.nwapw.abacus.context.MutableEvaluationContext; | ||||
| import org.nwapw.abacus.function.*; | ||||
| import org.nwapw.abacus.number.NaiveNumber; | ||||
| import org.nwapw.abacus.number.NumberInterface; | ||||
| import org.nwapw.abacus.number.PreciseNumber; | ||||
| import org.nwapw.abacus.tree.TreeNode; | ||||
| import org.nwapw.abacus.tree.VariableNode; | ||||
| import org.nwapw.abacus.plugin.NumberImplementation; | ||||
| import org.nwapw.abacus.plugin.Plugin; | ||||
| import org.nwapw.abacus.plugin.PluginManager; | ||||
| import org.nwapw.abacus.plugin.standard.operator.*; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashMap; | ||||
| @ -20,93 +22,27 @@ public class StandardPlugin extends Plugin { | ||||
|     /** | ||||
|      * The set operator. | ||||
|      */ | ||||
|     public final TreeValueOperator opSet = new TreeValueOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) { | ||||
|         @Override | ||||
|         public boolean matchesParams(MutableEvaluationContext context, TreeNode[] params) { | ||||
|             return params.length == 2 && params[0] instanceof VariableNode; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public NumberInterface applyInternal(MutableEvaluationContext context, TreeNode[] params) { | ||||
|             String assignTo = ((VariableNode) params[0]).getVariable(); | ||||
|             NumberInterface value = params[1].reduce(context.getInheritedReducer()); | ||||
|             context.setVariable(assignTo, value); | ||||
|             return value; | ||||
|         } | ||||
|     }; | ||||
|     public static final TreeValueOperator OP_SET = new OperatorSet(); | ||||
|     /** | ||||
|      * The define operator. | ||||
|      */ | ||||
|     public final TreeValueOperator opDefine = new TreeValueOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) { | ||||
|         @Override | ||||
|         public boolean matchesParams(MutableEvaluationContext context, TreeNode[] params) { | ||||
|             return params.length == 2 && params[0] instanceof VariableNode; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public NumberInterface applyInternal(MutableEvaluationContext context, TreeNode[] params) { | ||||
|             String assignTo = ((VariableNode) params[0]).getVariable(); | ||||
|             context.setDefinition(assignTo, params[1]); | ||||
|             return params[1].reduce(context.getInheritedReducer()); | ||||
|         } | ||||
|     }; | ||||
|     public final TreeValueOperator OP_DEFINE = new OperatorDefine(); | ||||
|     /** | ||||
|      * The addition operator, + | ||||
|      */ | ||||
|     public static final NumberOperator OP_ADD = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) { | ||||
|         @Override | ||||
|         public boolean matchesParams(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             return params.length == 2; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public NumberInterface applyInternal(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             return params[0].add(params[1]); | ||||
|         } | ||||
|     }; | ||||
|     public static final NumberOperator OP_ADD = new OperatorAdd(); | ||||
|     /** | ||||
|      * The subtraction operator, - | ||||
|      */ | ||||
|     public static final NumberOperator OP_SUBTRACT = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) { | ||||
|         @Override | ||||
|         public boolean matchesParams(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             return params.length == 2; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public NumberInterface applyInternal(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             return params[0].subtract(params[1]); | ||||
| 
 | ||||
|         } | ||||
|     }; | ||||
|     public static final NumberOperator OP_SUBTRACT = new OperatorSubtract(); | ||||
|     /** | ||||
|      * The negation operator, - | ||||
|      */ | ||||
|     public static final NumberOperator OP_NEGATE = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.UNARY_PREFIX, 0) { | ||||
|         @Override | ||||
|         public boolean matchesParams(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             return params.length == 1; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public NumberInterface applyInternal(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             return params[0].negate(); | ||||
|         } | ||||
|     }; | ||||
|     public static final NumberOperator OP_NEGATE = new OperatorNegate(); | ||||
|     /** | ||||
|      * The multiplication operator, * | ||||
|      */ | ||||
|     public static final NumberOperator OP_MULTIPLY = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 1) { | ||||
|         @Override | ||||
|         public boolean matchesParams(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             return params.length == 2; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public NumberInterface applyInternal(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             return params[0].multiply(params[1]); | ||||
|         } | ||||
|     }; | ||||
|     public static final NumberOperator OP_MULTIPLY = new OperatorMultiply(); | ||||
|     /** | ||||
|      * The implementation for double-based naive numbers. | ||||
|      */ | ||||
| @ -161,96 +97,19 @@ public class StandardPlugin extends Plugin { | ||||
|     /** | ||||
|      * The division operator, / | ||||
|      */ | ||||
|     public static final NumberOperator OP_DIVIDE = new NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 1) { | ||||
|         @Override | ||||
|         public boolean matchesParams(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             return params.length == 2 && params[1].compareTo(context.getInheritedNumberImplementation().instanceForString(Integer.toString(0))) != 0; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public NumberInterface applyInternal(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             return params[0].divide(params[1]); | ||||
|         } | ||||
|     }; | ||||
|     public static final NumberOperator OP_DIVIDE = new OperatorDivide(); | ||||
|     /** | ||||
|      * The factorial operator, ! | ||||
|      */ | ||||
|     public static final NumberOperator OP_FACTORIAL = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.UNARY_POSTFIX, 0) { | ||||
|         //private HashMap<Class<? extends NumberInterface>, ArrayList<NumberInterface>> storedList = new HashMap<Class<? extends NumberInterface>, ArrayList<NumberInterface>>(); | ||||
|         @Override | ||||
|         public boolean matchesParams(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             return params.length == 1 | ||||
|                     && params[0].fractionalPart().compareTo(context.getInheritedNumberImplementation().instanceForString("0")) == 0 | ||||
|                     && params[0].signum() >= 0; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public NumberInterface applyInternal(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             NumberImplementation implementation = context.getInheritedNumberImplementation(); | ||||
|             if (params[0].signum() == 0) { | ||||
|                 return implementation.instanceForString("1"); | ||||
|             } | ||||
|             NumberInterface one = implementation.instanceForString("1"); | ||||
|             NumberInterface factorial = params[0]; | ||||
|             NumberInterface multiplier = params[0]; | ||||
|             //It is necessary to later prevent calls of factorial on anything but non-negative integers. | ||||
|             while ((multiplier = multiplier.subtract(one)).signum() == 1) { | ||||
|                 factorial = factorial.multiply(multiplier); | ||||
|             } | ||||
|             return factorial; | ||||
|                 /*if(!storedList.containsKey(params[0].getClass())){ | ||||
|                     storedList.put(params[0].getClass(), new ArrayList<NumberInterface>()); | ||||
|                     storedList.get(params[0].getClass()).add(NaiveNumber.ONE.promoteTo(params[0].getClass())); | ||||
|                     storedList.get(params[0].getClass()).add(NaiveNumber.ONE.promoteTo(params[0].getClass())); | ||||
|                 }*/ | ||||
|         } | ||||
|     }; | ||||
|     public static final NumberOperator OP_FACTORIAL = new OperatorFactorial(); | ||||
|     /** | ||||
|      * The permutation operator. | ||||
|      */ | ||||
|     public static final NumberOperator OP_NPR = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0) { | ||||
|         @Override | ||||
|         public boolean matchesParams(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             return params.length == 2 && params[0].fractionalPart().signum() == 0 | ||||
|                     && params[1].fractionalPart().signum() == 0; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public NumberInterface applyInternal(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             NumberImplementation implementation = context.getInheritedNumberImplementation(); | ||||
|             if (params[0].compareTo(params[1]) < 0 || | ||||
|                     params[0].signum() < 0 || | ||||
|                     (params[0].signum() == 0 && params[1].signum() != 0)) return implementation.instanceForString("0"); | ||||
|             NumberInterface total = implementation.instanceForString("1"); | ||||
|             NumberInterface multiplyBy = params[0]; | ||||
|             NumberInterface remainingMultiplications = params[1]; | ||||
|             NumberInterface halfway = params[0].divide(implementation.instanceForString("2")); | ||||
|             if (remainingMultiplications.compareTo(halfway) > 0) { | ||||
|                 remainingMultiplications = params[0].subtract(remainingMultiplications); | ||||
|             } | ||||
|             while (remainingMultiplications.signum() > 0) { | ||||
|                 total = total.multiply(multiplyBy); | ||||
|                 remainingMultiplications = remainingMultiplications.subtract(implementation.instanceForString("1")); | ||||
|                 multiplyBy = multiplyBy.subtract(implementation.instanceForString("1")); | ||||
|             } | ||||
|             return total; | ||||
|         } | ||||
|     }; | ||||
|     public static final NumberOperator OP_NPR = new OperatorNpr(); | ||||
|     /** | ||||
|      * The combination operator. | ||||
|      */ | ||||
|     public static final NumberOperator OP_NCR = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0) { | ||||
|         @Override | ||||
|         public boolean matchesParams(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             return params.length == 2 && params[0].fractionalPart().signum() == 0 | ||||
|                     && params[1].fractionalPart().signum() == 0; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public NumberInterface applyInternal(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             return OP_NPR.apply(context, params).divide(OP_FACTORIAL.apply(context, params[1])); | ||||
|         } | ||||
|     }; | ||||
|     public static final NumberOperator OP_NCR = new OperatorNcr(); | ||||
|     /** | ||||
|      * The absolute value function, abs(-3) = 3 | ||||
|      */ | ||||
| @ -363,34 +222,7 @@ public class StandardPlugin extends Plugin { | ||||
|     /** | ||||
|      * The caret / pow operator, ^ | ||||
|      */ | ||||
|     public static final NumberOperator OP_CARET = new NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 2) { | ||||
|         @Override | ||||
|         public boolean matchesParams(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             NumberInterface zero = context.getInheritedNumberImplementation().instanceForString("0"); | ||||
|             return params.length == 2 | ||||
|                     && !(params[0].compareTo(zero) == 0 | ||||
|                     && params[1].compareTo(zero) == 0) | ||||
|                     && !(params[0].signum() == -1 && params[1].fractionalPart().compareTo(zero) != 0); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public NumberInterface applyInternal(MutableEvaluationContext context, NumberInterface[] params) { | ||||
|             NumberImplementation implementation = context.getInheritedNumberImplementation(); | ||||
|             NumberInterface zero = implementation.instanceForString("0"); | ||||
|             if (params[0].compareTo(zero) == 0) | ||||
|                 return zero; | ||||
|             else if (params[1].compareTo(zero) == 0) | ||||
|                 return implementation.instanceForString("1"); | ||||
|             //Detect integer bases: | ||||
|             if (params[0].fractionalPart().compareTo(implementation.instanceForString("0")) == 0 | ||||
|                     && FUNCTION_ABS.apply(context, params[1]).compareTo(implementation.instanceForString(Integer.toString(Integer.MAX_VALUE))) < 0 | ||||
|                     && FUNCTION_ABS.apply(context, params[1]).compareTo(implementation.instanceForString("1")) >= 0) { | ||||
|                 NumberInterface[] newParams = {params[0], params[1].fractionalPart()}; | ||||
|                 return params[0].intPow(params[1].floor().intValue()).multiply(applyInternal(context, newParams)); | ||||
|             } | ||||
|             return FUNCTION_EXP.apply(context, FUNCTION_LN.apply(context, FUNCTION_ABS.apply(context, params[0])).multiply(params[1])); | ||||
|         } | ||||
|     }; | ||||
|     public static final NumberOperator OP_CARET = new OperatorCaret(); | ||||
|     /** | ||||
|      * The square root function. | ||||
|      */ | ||||
| @ -756,8 +588,8 @@ public class StandardPlugin extends Plugin { | ||||
|         registerOperator("^", OP_CARET); | ||||
|         registerOperator("!", OP_FACTORIAL); | ||||
| 
 | ||||
|         registerTreeValueOperator("=", opSet); | ||||
|         registerTreeValueOperator(":=", opDefine); | ||||
|         registerTreeValueOperator("=", OP_SET); | ||||
|         registerTreeValueOperator(":=", OP_DEFINE); | ||||
| 
 | ||||
|         registerOperator("nPr", OP_NPR); | ||||
|         registerOperator("nCr", OP_NCR); | ||||
| @ -8,7 +8,7 @@ import org.nwapw.abacus.parsing.LexerTokenizer | ||||
| import org.nwapw.abacus.parsing.ShuntingYardParser | ||||
| import org.nwapw.abacus.parsing.TreeBuilder | ||||
| import org.nwapw.abacus.plugin.PluginManager | ||||
| import org.nwapw.abacus.plugin.StandardPlugin | ||||
| import org.nwapw.abacus.plugin.standard.StandardPlugin | ||||
| import org.nwapw.abacus.tree.EvaluationResult | ||||
| import org.nwapw.abacus.tree.NumberReducer | ||||
| import org.nwapw.abacus.tree.TreeNode | ||||
|  | ||||
							
								
								
									
										521
									
								
								core/src/main/java/org/nwapw/abacus/number/NumberInterface.java → core/src/main/kotlin/org/nwapw/abacus/number/NumberInterface.kt
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										521
									
								
								core/src/main/java/org/nwapw/abacus/number/NumberInterface.java → core/src/main/kotlin/org/nwapw/abacus/number/NumberInterface.kt
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -1,253 +1,268 @@ | ||||
| package org.nwapw.abacus.number; | ||||
| 
 | ||||
| import org.nwapw.abacus.exception.ComputationInterruptedException; | ||||
| 
 | ||||
| /** | ||||
|  * An interface used to represent a number. | ||||
|  */ | ||||
| public abstract class NumberInterface implements Comparable<NumberInterface> { | ||||
| 
 | ||||
|     /** | ||||
|      * Check if the thread was interrupted and | ||||
|      * throw an exception to end the computation. | ||||
|      */ | ||||
|     private static void checkInterrupted() { | ||||
|         if (Thread.currentThread().isInterrupted()) | ||||
|             throw new ComputationInterruptedException(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * The maximum precision to which this number operates. | ||||
|      * | ||||
|      * @return the precision. | ||||
|      */ | ||||
|     public abstract int getMaxPrecision(); | ||||
| 
 | ||||
|     /** | ||||
|      * Multiplies this number by another, returning | ||||
|      * a new number instance. | ||||
|      * | ||||
|      * @param multiplier the multiplier | ||||
|      * @return the result of the multiplication. | ||||
|      */ | ||||
|     protected abstract NumberInterface multiplyInternal(NumberInterface multiplier); | ||||
| 
 | ||||
|     /** | ||||
|      * Multiplies this number by another, returning | ||||
|      * a new number instance. Also, checks if the | ||||
|      * thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @param multiplier the multiplier | ||||
|      * @return the result of the multiplication. | ||||
|      */ | ||||
|     public final NumberInterface multiply(NumberInterface multiplier) { | ||||
|         checkInterrupted(); | ||||
|         return multiplyInternal(multiplier); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Divides this number by another, returning | ||||
|      * a new number instance. | ||||
|      * | ||||
|      * @param divisor the divisor | ||||
|      * @return the result of the division. | ||||
|      */ | ||||
|     protected abstract NumberInterface divideInternal(NumberInterface divisor); | ||||
| 
 | ||||
|     /** | ||||
|      * Divides this number by another, returning | ||||
|      * a new number instance. Also, checks if the | ||||
|      * thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @param divisor the divisor | ||||
|      * @return the result of the division. | ||||
|      */ | ||||
|     public final NumberInterface divide(NumberInterface divisor) { | ||||
|         checkInterrupted(); | ||||
|         return divideInternal(divisor); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Adds this number to another, returning | ||||
|      * a new number instance. | ||||
|      * | ||||
|      * @param summand the summand | ||||
|      * @return the result of the summation. | ||||
|      */ | ||||
|     protected abstract NumberInterface addInternal(NumberInterface summand); | ||||
| 
 | ||||
|     /** | ||||
|      * Adds this number to another, returning | ||||
|      * a new number instance. Also, checks if the | ||||
|      * thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @param summand the summand | ||||
|      * @return the result of the summation. | ||||
|      */ | ||||
|     public final NumberInterface add(NumberInterface summand) { | ||||
|         checkInterrupted(); | ||||
|         return addInternal(summand); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Subtracts another number from this number, | ||||
|      * a new number instance. | ||||
|      * | ||||
|      * @param subtrahend the subtrahend. | ||||
|      * @return the result of the subtraction. | ||||
|      */ | ||||
|     protected abstract NumberInterface subtractInternal(NumberInterface subtrahend); | ||||
| 
 | ||||
|     /** | ||||
|      * Subtracts another number from this number, | ||||
|      * a new number instance. Also, checks if the | ||||
|      * thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @param subtrahend the subtrahend. | ||||
|      * @return the result of the subtraction. | ||||
|      */ | ||||
|     public final NumberInterface subtract(NumberInterface subtrahend) { | ||||
|         checkInterrupted(); | ||||
|         return subtractInternal(subtrahend); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns a new instance of this number with | ||||
|      * the sign flipped. | ||||
|      * | ||||
|      * @return the new instance. | ||||
|      */ | ||||
|     protected abstract NumberInterface negateInternal(); | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * Returns a new instance of this number with | ||||
|      * the sign flipped. Also, checks if the | ||||
|      * thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @return the new instance. | ||||
|      */ | ||||
|     public final NumberInterface negate() { | ||||
|         checkInterrupted(); | ||||
|         return negateInternal(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Raises this number to an integer power. | ||||
|      * | ||||
|      * @param exponent the exponent to which to take the number. | ||||
|      * @return the resulting value. | ||||
|      */ | ||||
|     protected abstract NumberInterface intPowInternal(int exponent); | ||||
| 
 | ||||
|     /** | ||||
|      * Raises this number to an integer power. Also, checks if the | ||||
|      * thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @param exponent the exponent to which to take the number. | ||||
|      * @return the resulting value. | ||||
|      */ | ||||
|     public final NumberInterface intPow(int exponent) { | ||||
|         checkInterrupted(); | ||||
|         return intPowInternal(exponent); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Same as Math.signum(). | ||||
|      * | ||||
|      * @return 1 if this number is positive, -1 if this number is negative, 0 if this number is 0. | ||||
|      */ | ||||
|     public abstract int signum(); | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the least integer greater than or equal to the number. | ||||
|      * | ||||
|      * @return the least integer greater or equal to the number, if int can hold the value. | ||||
|      */ | ||||
|     protected abstract NumberInterface ceilingInternal(); | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the least integer greater than or equal to the number. | ||||
|      * Also, checks if the thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @return the least integer bigger or equal to the number. | ||||
|      */ | ||||
|     public final NumberInterface ceiling() { | ||||
|         checkInterrupted(); | ||||
|         return ceilingInternal(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Return the greatest integer less than or equal to the number. | ||||
|      * | ||||
|      * @return the greatest integer smaller or equal the number. | ||||
|      */ | ||||
|     protected abstract NumberInterface floorInternal(); | ||||
| 
 | ||||
|     /** | ||||
|      * Return the greatest integer less than or equal to the number. | ||||
|      * Also, checks if the thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @return the greatest int smaller than or equal to the number. | ||||
|      */ | ||||
|     public final NumberInterface floor() { | ||||
|         checkInterrupted(); | ||||
|         return floorInternal(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the fractional part of the number. | ||||
|      * | ||||
|      * @return the fractional part of the number. | ||||
|      */ | ||||
|     protected abstract NumberInterface fractionalPartInternal(); | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the fractional part of the number, specifically x - floor(x). | ||||
|      * Also, checks if the thread has been interrupted, | ||||
|      * and if so, throws an exception. | ||||
|      * | ||||
|      * @return the fractional part of the number. | ||||
|      */ | ||||
|     public final NumberInterface fractionalPart() { | ||||
|         checkInterrupted(); | ||||
|         return fractionalPartInternal(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the integer representation of this number, discarding any fractional part, | ||||
|      * if int can hold the value. | ||||
|      * | ||||
|      * @return the integer value of this number. | ||||
|      */ | ||||
|     public abstract int intValue(); | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the smallest error this instance can tolerate depending | ||||
|      * on its precision and value. | ||||
|      * | ||||
|      * @return the smallest error that should be permitted in calculations. | ||||
|      */ | ||||
|     public abstract NumberInterface getMaxError(); | ||||
| 
 | ||||
|     /** | ||||
|      * Returns a NumberRangeBuilder object, which is used to create a range. | ||||
|      * The reason that this returns a builder and not an actual range is that | ||||
|      * the NumberRange needs to promote values passed to it, which | ||||
|      * requires an abacus instance. | ||||
|      * @param other the value at the bottom of the range. | ||||
|      * @return the resulting range builder. | ||||
|      */ | ||||
|     public NumberRangeBuilder rangeTo(NumberInterface other){ | ||||
|         return new NumberRangeBuilder(this, other); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| package org.nwapw.abacus.number | ||||
| 
 | ||||
| import org.nwapw.abacus.exception.ComputationInterruptedException | ||||
| 
 | ||||
| abstract class NumberInterface: Comparable<NumberInterface> { | ||||
| 
 | ||||
|     /** | ||||
|      * Check if the thread was interrupted and | ||||
|      * throw an exception to end the computation. | ||||
|      */ | ||||
|     private fun checkInterrupted(){ | ||||
|         if(Thread.currentThread().isInterrupted) | ||||
|             throw ComputationInterruptedException() | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the integer representation of this number, discarding any fractional part, | ||||
|      * if int can hold the value. | ||||
|      * | ||||
|      * @return the integer value of this number. | ||||
|      */ | ||||
|     abstract fun intValue(): Int | ||||
|     /** | ||||
|      * Same as Math.signum(). | ||||
|      * | ||||
|      * @return 1 if this number is positive, -1 if this number is negative, 0 if this number is 0. | ||||
|      */ | ||||
|     abstract fun signum(): Int | ||||
| 
 | ||||
|     /** | ||||
|      * The maximum precision to which this number operates. | ||||
|      */ | ||||
|     abstract val maxPrecision: Int | ||||
|     /** | ||||
|      * Returns the smallest error this instance can tolerate depending | ||||
|      * on its precision and value. | ||||
|      */ | ||||
|     abstract val maxError: NumberInterface | ||||
| 
 | ||||
|     /** | ||||
|      * Adds this number to another, returning | ||||
|      * a new number instance. | ||||
|      * | ||||
|      * @param summand the summand | ||||
|      * @return the result of the summation. | ||||
|      */ | ||||
|     abstract fun addInternal(summand: NumberInterface): NumberInterface | ||||
|     /** | ||||
|      * Subtracts another number from this number, | ||||
|      * a new number instance. | ||||
|      * | ||||
|      * @param subtrahend the subtrahend. | ||||
|      * @return the result of the subtraction. | ||||
|      */ | ||||
|     abstract fun subtractInternal(subtrahend: NumberInterface): NumberInterface | ||||
|     /** | ||||
|      * Multiplies this number by another, returning | ||||
|      * a new number instance. | ||||
|      * | ||||
|      * @param multiplier the multiplier | ||||
|      * @return the result of the multiplication. | ||||
|      */ | ||||
|     abstract fun multiplyInternal(multiplier: NumberInterface): NumberInterface | ||||
|     /** | ||||
|      * Divides this number by another, returning | ||||
|      * a new number instance. | ||||
|      * | ||||
|      * @param divisor the divisor | ||||
|      * @return the result of the division. | ||||
|      */ | ||||
|     abstract fun divideInternal(divisor: NumberInterface): NumberInterface | ||||
|     /** | ||||
|      * Returns a new instance of this number with | ||||
|      * the sign flipped. | ||||
|      * | ||||
|      * @return the new instance. | ||||
|      */ | ||||
|     abstract fun negateInternal(): NumberInterface | ||||
|     /** | ||||
|      * Raises this number to an integer power. | ||||
|      * | ||||
|      * @param exponent the exponent to which to take the number. | ||||
|      * @return the resulting value. | ||||
|      */ | ||||
|     abstract fun intPowInternal(pow: Int): NumberInterface | ||||
|     /** | ||||
|      * Returns the least integer greater than or equal to the number. | ||||
|      * | ||||
|      * @return the least integer greater or equal to the number, if int can hold the value. | ||||
|      */ | ||||
|     abstract fun ceilingInternal(): NumberInterface | ||||
|     /** | ||||
|      * Return the greatest integer less than or equal to the number. | ||||
|      * | ||||
|      * @return the greatest integer smaller or equal the number. | ||||
|      */ | ||||
|     abstract fun floorInternal(): NumberInterface | ||||
|     /** | ||||
|      * Returns the fractional part of the number. | ||||
|      * | ||||
|      * @return the fractional part of the number. | ||||
|      */ | ||||
|     abstract fun fractionalPartInternal(): NumberInterface | ||||
| 
 | ||||
|     /** | ||||
|      * Adds this number to another, returning | ||||
|      * a new number instance. Also, checks if the | ||||
|      * thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @param summand the summand | ||||
|      * @return the result of the summation. | ||||
|      */ | ||||
|     fun add(summand: NumberInterface): NumberInterface { | ||||
|         checkInterrupted() | ||||
|         return addInternal(summand) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Subtracts another number from this number, | ||||
|      * a new number instance. Also, checks if the | ||||
|      * thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @param subtrahend the subtrahend. | ||||
|      * @return the result of the subtraction. | ||||
|      */ | ||||
|     fun subtract(subtrahend: NumberInterface): NumberInterface { | ||||
|         checkInterrupted() | ||||
|         return subtractInternal(subtrahend) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Multiplies this number by another, returning | ||||
|      * a new number instance. Also, checks if the | ||||
|      * thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @param multiplier the multiplier | ||||
|      * @return the result of the multiplication. | ||||
|      */ | ||||
|     fun multiply(multiplier: NumberInterface): NumberInterface { | ||||
|         checkInterrupted() | ||||
|         return multiplyInternal(multiplier) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Divides this number by another, returning | ||||
|      * a new number instance. Also, checks if the | ||||
|      * thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @param divisor the divisor | ||||
|      * @return the result of the division. | ||||
|      */ | ||||
|     fun divide(divisor: NumberInterface): NumberInterface { | ||||
|         checkInterrupted() | ||||
|         return divideInternal(divisor) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns a new instance of this number with | ||||
|      * the sign flipped. Also, checks if the | ||||
|      * thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @return the new instance. | ||||
|      */ | ||||
|     fun negate(): NumberInterface { | ||||
|         checkInterrupted() | ||||
|         return negateInternal() | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Raises this number to an integer power. Also, checks if the | ||||
|      * thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @param exponent the exponent to which to take the number. | ||||
|      * @return the resulting value. | ||||
|      */ | ||||
|     fun intPow(exponent: Int): NumberInterface { | ||||
|         checkInterrupted() | ||||
|         return intPowInternal(exponent) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the least integer greater than or equal to the number. | ||||
|      * Also, checks if the thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @return the least integer bigger or equal to the number. | ||||
|      */ | ||||
|     fun ceiling(): NumberInterface { | ||||
|         checkInterrupted() | ||||
|         return ceilingInternal() | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Return the greatest integer less than or equal to the number. | ||||
|      * Also, checks if the thread has been interrupted, and if so, throws | ||||
|      * an exception. | ||||
|      * | ||||
|      * @return the greatest int smaller than or equal to the number. | ||||
|      */ | ||||
|     fun floor(): NumberInterface { | ||||
|         checkInterrupted() | ||||
|         return floorInternal() | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the fractional part of the number, specifically x - floor(x). | ||||
|      * Also, checks if the thread has been interrupted, | ||||
|      * and if so, throws an exception. | ||||
|      * | ||||
|      * @return the fractional part of the number. | ||||
|      */ | ||||
|     fun fractionalPart(): NumberInterface { | ||||
|         checkInterrupted() | ||||
|         return fractionalPartInternal() | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns a NumberRangeBuilder object, which is used to create a range. | ||||
|      * The reason that this returns a builder and not an actual range is that | ||||
|      * the NumberRange needs to promote values passed to it, which | ||||
|      * requires an abacus instance. | ||||
|      * @param other the value at the bottom of the range. | ||||
|      * @return the resulting range builder. | ||||
|      */ | ||||
|     operator fun rangeTo(other: NumberInterface) = NumberRangeBuilder(this, other) | ||||
| 
 | ||||
|     /** | ||||
|      * Plus operator overloaded to allow "nice" looking math. | ||||
|      * @param other the value to add to this number. | ||||
|      * @return the result of the addition. | ||||
|      */ | ||||
|     operator fun plus(other: NumberInterface) = add(other) | ||||
|     /** | ||||
|      * Minus operator overloaded to allow "nice" looking math. | ||||
|      * @param other the value to subtract to this number. | ||||
|      * @return the result of the subtraction. | ||||
|      */ | ||||
|     operator fun minus(other: NumberInterface) = subtract(other) | ||||
|     /** | ||||
|      * Times operator overloaded to allow "nice" looking math. | ||||
|      * @param other the value to multiply this number by. | ||||
|      * @return the result of the multiplication. | ||||
|      */ | ||||
|     operator fun times(other: NumberInterface) = multiply(other) | ||||
|     /** | ||||
|      * Divide operator overloaded to allow "nice" looking math. | ||||
|      * @param other the value to divide this number by. | ||||
|      * @return the result of the division. | ||||
|      */ | ||||
|     operator fun div(other: NumberInterface) = divide(other) | ||||
|     /** | ||||
|      * The plus operator. | ||||
|      * @return this number. | ||||
|      */ | ||||
|     operator fun unaryPlus() = this | ||||
|     /** | ||||
|      * The minus operator. | ||||
|      * @return the negative of this number. | ||||
|      */ | ||||
|     operator fun unaryMinus() = negate() | ||||
| 
 | ||||
| } | ||||
| @ -1,16 +1,17 @@ | ||||
| package org.nwapw.abacus.parsing; | ||||
| package org.nwapw.abacus.parsing | ||||
| 
 | ||||
| import org.nwapw.abacus.tree.TreeNode; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import org.nwapw.abacus.tree.TreeNode | ||||
| 
 | ||||
| /** | ||||
|  * An itnerface that provides the ability to convert a list of tokens | ||||
|  * Converter from tokens into a parse tree. | ||||
|  * | ||||
|  * An interface that provides the ability to convert a list of tokens | ||||
|  * into a parse tree. | ||||
|  * | ||||
|  * @param <T> the type of tokens accepted by this parser. | ||||
|  */ | ||||
| public interface Parser<T> { | ||||
| 
 | ||||
| interface Parser<in T> { | ||||
| 
 | ||||
|     /** | ||||
|      * Constructs a tree out of the given tokens. | ||||
| @ -18,5 +19,6 @@ public interface Parser<T> { | ||||
|      * @param tokens the tokens to construct a tree from. | ||||
|      * @return the constructed tree, or null on error. | ||||
|      */ | ||||
|     public TreeNode constructTree(List<T> tokens); | ||||
| } | ||||
|     fun constructTree(tokens: List<T>): TreeNode | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										21
									
								
								core/src/main/kotlin/org/nwapw/abacus/parsing/Tokenizer.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								core/src/main/kotlin/org/nwapw/abacus/parsing/Tokenizer.kt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| package org.nwapw.abacus.parsing | ||||
| 
 | ||||
| /** | ||||
|  * Converter from string to tokens. | ||||
|  * | ||||
|  * Interface that converts a string into a list | ||||
|  * of tokens of a certain type. | ||||
|  * | ||||
|  * @param <T> the type of the tokens produced. | ||||
|  */ | ||||
| interface Tokenizer<out T> { | ||||
| 
 | ||||
|     /** | ||||
|      * Converts a string into tokens. | ||||
|      * | ||||
|      * @param string the string to convert. | ||||
|      * @return the list of tokens, or null on error. | ||||
|      */ | ||||
|     fun tokenizeString(string: String):  List<T> | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										26
									
								
								core/src/main/kotlin/org/nwapw/abacus/parsing/TreeBuilder.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								core/src/main/kotlin/org/nwapw/abacus/parsing/TreeBuilder.kt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| package org.nwapw.abacus.parsing | ||||
| 
 | ||||
| import org.nwapw.abacus.tree.TreeNode | ||||
| 
 | ||||
| /** | ||||
|  * Class to combine a [Tokenizer] and a [Parser] | ||||
|  * | ||||
|  * TreeBuilder class used to piece together a Tokenizer and | ||||
|  * Parser of the same kind. This is used to essentially avoid | ||||
|  * working with any parameters at all, and the generics | ||||
|  * in this class are used only to ensure the tokenizer and parser | ||||
|  * are of the same type. | ||||
|  * | ||||
|  * @param <T> the type of tokens created by the tokenizer and used by the parser. | ||||
|  */ | ||||
| class TreeBuilder<T>(private val tokenizer: Tokenizer<T>, private val parser: Parser<T>) { | ||||
| 
 | ||||
|     /** | ||||
|      * Parses the given [string] into a tree. | ||||
|      * | ||||
|      * @param string the string to parse into a tree. | ||||
|      * @return the resulting tree. | ||||
|      */ | ||||
|     fun fromString(string: String): TreeNode = parser.constructTree(tokenizer.tokenizeString(string)) | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,21 @@ | ||||
| package org.nwapw.abacus.plugin.standard.operator | ||||
| 
 | ||||
| import org.nwapw.abacus.context.MutableEvaluationContext | ||||
| import org.nwapw.abacus.function.NumberOperator | ||||
| import org.nwapw.abacus.function.OperatorAssociativity | ||||
| import org.nwapw.abacus.function.OperatorType | ||||
| import org.nwapw.abacus.number.NumberInterface | ||||
| 
 | ||||
| /** | ||||
|  * The addition operator. | ||||
|  * | ||||
|  * This is a standard operator that simply performs addition. | ||||
|  */ | ||||
| class OperatorAdd: NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) { | ||||
| 
 | ||||
|     override fun matchesParams(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|             params.size == 2 | ||||
|     override fun applyInternal(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|             params[0] + params[1] | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,38 @@ | ||||
| package org.nwapw.abacus.plugin.standard.operator | ||||
| 
 | ||||
| import org.nwapw.abacus.context.MutableEvaluationContext | ||||
| import org.nwapw.abacus.function.NumberOperator | ||||
| import org.nwapw.abacus.function.OperatorAssociativity | ||||
| import org.nwapw.abacus.function.OperatorType | ||||
| import org.nwapw.abacus.number.NumberInterface | ||||
| import org.nwapw.abacus.plugin.standard.StandardPlugin.* | ||||
| 
 | ||||
| /** | ||||
|  * The power operator. | ||||
|  * | ||||
|  * This is a standard operator that brings one number to the power of the other. | ||||
|  */ | ||||
| class OperatorCaret: NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 2) { | ||||
| 
 | ||||
|     override fun matchesParams(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|             params.size == 2 | ||||
|                     && !(params[0].signum() == 0 && params[1].signum() == 0) | ||||
|                     && !(params[0].signum() == -1 && params[1].fractionalPart().signum() != 0) | ||||
| 
 | ||||
|     override fun applyInternal(context: MutableEvaluationContext, params: Array<out NumberInterface>): NumberInterface { | ||||
|         val implementation = context.inheritedNumberImplementation | ||||
|         if (params[0].signum() == 0) | ||||
|             return implementation.instanceForString("0") | ||||
|         else if (params[1].signum() == 0) | ||||
|             return implementation.instanceForString("1") | ||||
|         //Detect integer bases: | ||||
|         if (params[0].fractionalPart().signum() == 0 | ||||
|                 && FUNCTION_ABS.apply(context, params[1]) < implementation.instanceForString(Integer.toString(Integer.MAX_VALUE)) | ||||
|                 && FUNCTION_ABS.apply(context, params[1]) >= implementation.instanceForString("1")) { | ||||
|             val newParams = arrayOf(params[0], params[1].fractionalPart()) | ||||
|             return params[0].intPow(params[1].floor().intValue()) * applyInternal(context, newParams) | ||||
|         } | ||||
|         return FUNCTION_EXP.apply(context, FUNCTION_LN.apply(context, FUNCTION_ABS.apply(context, params[0])) * params[1]) | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,28 @@ | ||||
| package org.nwapw.abacus.plugin.standard.operator | ||||
| 
 | ||||
| import org.nwapw.abacus.context.MutableEvaluationContext | ||||
| import org.nwapw.abacus.function.OperatorAssociativity | ||||
| import org.nwapw.abacus.function.OperatorType | ||||
| import org.nwapw.abacus.function.TreeValueOperator | ||||
| import org.nwapw.abacus.number.NumberInterface | ||||
| import org.nwapw.abacus.tree.TreeNode | ||||
| import org.nwapw.abacus.tree.VariableNode | ||||
| 
 | ||||
| /** | ||||
|  * The definition operator. | ||||
|  * | ||||
|  * This is a standard operator that creates a definition - something that doesn't capture variable values | ||||
|  * when it's created, but rather the variables themselves, and changes when the variables it uses change. | ||||
|  */ | ||||
| class OperatorDefine: TreeValueOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) { | ||||
| 
 | ||||
|     override fun matchesParams(context: MutableEvaluationContext, params: Array<out TreeNode>) = | ||||
|             params.size == 2 && params[0] is VariableNode | ||||
| 
 | ||||
|     override fun applyInternal(context: MutableEvaluationContext, params: Array<out TreeNode>): NumberInterface { | ||||
|         val assignTo = (params[0] as VariableNode).variable | ||||
|         context.setDefinition(assignTo, params[1]) | ||||
|         return params[1].reduce(context.inheritedReducer) | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,21 @@ | ||||
| package org.nwapw.abacus.plugin.standard.operator | ||||
| 
 | ||||
| import org.nwapw.abacus.context.MutableEvaluationContext | ||||
| import org.nwapw.abacus.function.NumberOperator | ||||
| import org.nwapw.abacus.function.OperatorAssociativity | ||||
| import org.nwapw.abacus.function.OperatorType | ||||
| import org.nwapw.abacus.number.NumberInterface | ||||
| 
 | ||||
| /** | ||||
|  * The division operator. | ||||
|  * | ||||
|  * This is a standard operator that simply performs division. | ||||
|  */ | ||||
| class OperatorDivide: NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 1) { | ||||
| 
 | ||||
|     override fun matchesParams(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|             params.size == 2 | ||||
|     override fun applyInternal(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|             params[0] / params[1] | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,37 @@ | ||||
| package org.nwapw.abacus.plugin.standard.operator | ||||
| 
 | ||||
| import org.nwapw.abacus.context.MutableEvaluationContext | ||||
| import org.nwapw.abacus.function.NumberOperator | ||||
| import org.nwapw.abacus.function.OperatorAssociativity | ||||
| import org.nwapw.abacus.function.OperatorType | ||||
| import org.nwapw.abacus.number.NumberInterface | ||||
| 
 | ||||
| /** | ||||
|  * The factorial operator. | ||||
|  * | ||||
|  * This is a standard operator that simply evaluates the factorial of a number. | ||||
|  */ | ||||
| class OperatorFactorial: NumberOperator(OperatorAssociativity.LEFT, OperatorType.UNARY_POSTFIX, 0) { | ||||
| 
 | ||||
|     override fun matchesParams(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|         params.size == 1 | ||||
|                 && params[0].fractionalPart().signum() == 0 | ||||
|                 && params[0].signum() >= 0 | ||||
| 
 | ||||
|     override fun applyInternal(context: MutableEvaluationContext, params: Array<out NumberInterface>): NumberInterface { | ||||
|         val implementation = context.inheritedNumberImplementation | ||||
|         val one = implementation.instanceForString("1") | ||||
|         if (params[0].signum() == 0) { | ||||
|             return one | ||||
|         } | ||||
|         var factorial = params[0] | ||||
|         var multiplier = params[0] - one | ||||
|         //It is necessary to later prevent calls of factorial on anything but non-negative integers. | ||||
|         while (multiplier.signum() == 1) { | ||||
|             factorial *= multiplier | ||||
|             multiplier -= one | ||||
|         } | ||||
|         return factorial | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,21 @@ | ||||
| package org.nwapw.abacus.plugin.standard.operator | ||||
| 
 | ||||
| import org.nwapw.abacus.context.MutableEvaluationContext | ||||
| import org.nwapw.abacus.function.NumberOperator | ||||
| import org.nwapw.abacus.function.OperatorAssociativity | ||||
| import org.nwapw.abacus.function.OperatorType | ||||
| import org.nwapw.abacus.number.NumberInterface | ||||
| 
 | ||||
| /** | ||||
|  * The multiplication operator. | ||||
|  * | ||||
|  * This is a standard operator that simply performs multiplication. | ||||
|  */ | ||||
| class OperatorMultiply: NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 1) { | ||||
| 
 | ||||
|     override fun matchesParams(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|             params.size == 2 | ||||
|     override fun applyInternal(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|             params[0] * params[1] | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,25 @@ | ||||
| package org.nwapw.abacus.plugin.standard.operator | ||||
| 
 | ||||
| import org.nwapw.abacus.context.MutableEvaluationContext | ||||
| import org.nwapw.abacus.function.NumberOperator | ||||
| import org.nwapw.abacus.function.OperatorAssociativity | ||||
| import org.nwapw.abacus.function.OperatorType | ||||
| import org.nwapw.abacus.number.NumberInterface | ||||
| import org.nwapw.abacus.plugin.standard.StandardPlugin.* | ||||
| 
 | ||||
| /** | ||||
|  * The "N choose R" operator. | ||||
|  * | ||||
|  * This is a standard operator that returns the number of possible combinations, regardless of order, | ||||
|  * of a certain size can be taken out of a pool of a bigger size. | ||||
|  */ | ||||
| class OperatorNcr: NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0) { | ||||
| 
 | ||||
|     override fun matchesParams(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|             params.size == 2 && params[0].fractionalPart().signum() == 0 | ||||
|                     && params[1].fractionalPart().signum() == 0 | ||||
| 
 | ||||
|     override fun applyInternal(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|             OP_NPR.apply(context, *params) / OP_FACTORIAL.apply(context, params[1]) | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,22 @@ | ||||
| package org.nwapw.abacus.plugin.standard.operator | ||||
| 
 | ||||
| import org.nwapw.abacus.context.MutableEvaluationContext | ||||
| import org.nwapw.abacus.function.NumberOperator | ||||
| import org.nwapw.abacus.function.OperatorAssociativity | ||||
| import org.nwapw.abacus.function.OperatorType | ||||
| import org.nwapw.abacus.number.NumberInterface | ||||
| 
 | ||||
| /** | ||||
|  * The negation operator. | ||||
|  * | ||||
|  * This is a standard operator that negates a number. | ||||
|  */ | ||||
| class OperatorNegate: NumberOperator(OperatorAssociativity.LEFT, OperatorType.UNARY_PREFIX, 0) { | ||||
| 
 | ||||
|     override fun matchesParams(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|             params.size == 1 | ||||
| 
 | ||||
|     override fun applyInternal(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|             -params[0] | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,42 @@ | ||||
| package org.nwapw.abacus.plugin.standard.operator | ||||
| 
 | ||||
| import org.nwapw.abacus.context.MutableEvaluationContext | ||||
| import org.nwapw.abacus.function.NumberOperator | ||||
| import org.nwapw.abacus.function.OperatorAssociativity | ||||
| import org.nwapw.abacus.function.OperatorType | ||||
| import org.nwapw.abacus.number.NumberInterface | ||||
| 
 | ||||
| /** | ||||
|  * The "N pick R" operator. | ||||
|  * | ||||
|  * his is a standard operator that returns the number of possible combinations | ||||
|  * of a certain size can be taken out of a pool of a bigger size. | ||||
|  */ | ||||
| class OperatorNpr: NumberOperator(OperatorAssociativity.RIGHT, OperatorType.BINARY_INFIX, 0) { | ||||
| 
 | ||||
|     override fun matchesParams(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|             params.size == 2 && params[0].fractionalPart().signum() == 0 | ||||
|                     && params[1].fractionalPart().signum() == 0 | ||||
| 
 | ||||
|     override fun applyInternal(context: MutableEvaluationContext, params: Array<out NumberInterface>): NumberInterface { | ||||
|         val implementation = context.inheritedNumberImplementation | ||||
|         if (params[0] < params[1] || | ||||
|                 params[0].signum() < 0 || | ||||
|                 params[0].signum() == 0 && params[1].signum() != 0) | ||||
|             return implementation.instanceForString("0") | ||||
|         var total = implementation.instanceForString("1") | ||||
|         var multiplyBy = params[0] | ||||
|         var remainingMultiplications = params[1] | ||||
|         val halfway = params[0] / implementation.instanceForString("2") | ||||
|         if (remainingMultiplications > halfway) { | ||||
|             remainingMultiplications = params[0] - remainingMultiplications | ||||
|         } | ||||
|         while (remainingMultiplications.signum() > 0) { | ||||
|             total *= multiplyBy | ||||
|             remainingMultiplications -= implementation.instanceForString("1") | ||||
|             multiplyBy -= implementation.instanceForString("1") | ||||
|         } | ||||
|         return total | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,28 @@ | ||||
| package org.nwapw.abacus.plugin.standard.operator | ||||
| 
 | ||||
| import org.nwapw.abacus.context.MutableEvaluationContext | ||||
| import org.nwapw.abacus.function.OperatorAssociativity | ||||
| import org.nwapw.abacus.function.OperatorType | ||||
| import org.nwapw.abacus.function.TreeValueOperator | ||||
| import org.nwapw.abacus.number.NumberInterface | ||||
| import org.nwapw.abacus.tree.TreeNode | ||||
| import org.nwapw.abacus.tree.VariableNode | ||||
| 
 | ||||
| /** | ||||
|  * The set operator. | ||||
|  * | ||||
|  * This is a standard operator that assigns a value to a variable name. | ||||
|  */ | ||||
| class OperatorSet: TreeValueOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) { | ||||
| 
 | ||||
|     override fun matchesParams(context: MutableEvaluationContext, params: Array<out TreeNode>) = | ||||
|             params.size == 2 && params[0] is VariableNode | ||||
| 
 | ||||
|     override fun applyInternal(context: MutableEvaluationContext, params: Array<out TreeNode>): NumberInterface { | ||||
|         val assignTo = (params[0] as VariableNode).variable | ||||
|         val value = params[1].reduce(context.inheritedReducer) | ||||
|         context.setVariable(assignTo, value) | ||||
|         return value | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,21 @@ | ||||
| package org.nwapw.abacus.plugin.standard.operator | ||||
| 
 | ||||
| import org.nwapw.abacus.context.MutableEvaluationContext | ||||
| import org.nwapw.abacus.function.NumberOperator | ||||
| import org.nwapw.abacus.function.OperatorAssociativity | ||||
| import org.nwapw.abacus.function.OperatorType | ||||
| import org.nwapw.abacus.number.NumberInterface | ||||
| 
 | ||||
| /** | ||||
|  * The subtraction operator. | ||||
|  * | ||||
|  * This is a standard operator that performs subtraction. | ||||
|  */ | ||||
| class OperatorSubtract: NumberOperator(OperatorAssociativity.LEFT, OperatorType.BINARY_INFIX, 0) { | ||||
| 
 | ||||
|     override fun matchesParams(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|             params.size == 2 | ||||
|     override fun applyInternal(context: MutableEvaluationContext, params: Array<out NumberInterface>) = | ||||
|             params[0] - params[1] | ||||
| 
 | ||||
| } | ||||
| @ -7,7 +7,7 @@ import org.nwapw.abacus.Abacus; | ||||
| import org.nwapw.abacus.config.Configuration; | ||||
| import org.nwapw.abacus.exception.DomainException; | ||||
| import org.nwapw.abacus.number.NumberInterface; | ||||
| import org.nwapw.abacus.plugin.StandardPlugin; | ||||
| import org.nwapw.abacus.plugin.standard.StandardPlugin; | ||||
| import org.nwapw.abacus.tree.TreeNode; | ||||
| 
 | ||||
| public class CalculationTests { | ||||
|  | ||||
| @ -9,7 +9,7 @@ import org.nwapw.abacus.number.NaiveNumber; | ||||
| import org.nwapw.abacus.number.NumberInterface; | ||||
| import org.nwapw.abacus.number.NumberRange; | ||||
| import org.nwapw.abacus.number.PreciseNumber; | ||||
| import org.nwapw.abacus.plugin.StandardPlugin; | ||||
| import org.nwapw.abacus.plugin.standard.StandardPlugin; | ||||
| 
 | ||||
| import java.util.function.Function; | ||||
| 
 | ||||
|  | ||||
| @ -19,7 +19,7 @@ import org.nwapw.abacus.number.*; | ||||
| import org.nwapw.abacus.plugin.ClassFinder; | ||||
| import org.nwapw.abacus.plugin.PluginListener; | ||||
| import org.nwapw.abacus.plugin.PluginManager; | ||||
| import org.nwapw.abacus.plugin.StandardPlugin; | ||||
| import org.nwapw.abacus.plugin.standard.StandardPlugin; | ||||
| import org.nwapw.abacus.tree.EvaluationResult; | ||||
| import org.nwapw.abacus.tree.TreeNode; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user