Add remainder function
This commit is contained in:
		
							parent
							
								
									6a4d19517e
								
							
						
					
					
						commit
						735f1d584a
					
				
							
								
								
									
										35
									
								
								src/function/builtin/math/REMAINDER.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/function/builtin/math/REMAINDER.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					package function.builtin.math;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import function.ArgumentValidator;
 | 
				
			||||||
 | 
					import function.FunctionNames;
 | 
				
			||||||
 | 
					import function.LispFunction;
 | 
				
			||||||
 | 
					import function.builtin.math.DIVIDE.DivideByZeroException;
 | 
				
			||||||
 | 
					import sexpression.Cons;
 | 
				
			||||||
 | 
					import sexpression.LispNumber;
 | 
				
			||||||
 | 
					import sexpression.SExpression;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@FunctionNames({ "REM", "REMAINDER" })
 | 
				
			||||||
 | 
					public class REMAINDER extends LispFunction {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private ArgumentValidator argumentValidator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public REMAINDER(String name) {
 | 
				
			||||||
 | 
					        this.argumentValidator = new ArgumentValidator(name);
 | 
				
			||||||
 | 
					        this.argumentValidator.setExactNumberOfArguments(2);
 | 
				
			||||||
 | 
					        this.argumentValidator.setEveryArgumentExpectedType(LispNumber.class);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public SExpression call(Cons argumentList) {
 | 
				
			||||||
 | 
					        argumentValidator.validate(argumentList);
 | 
				
			||||||
 | 
					        LispNumber dividend = (LispNumber) argumentList.getFirst();
 | 
				
			||||||
 | 
					        LispNumber divisor = (LispNumber) ((Cons) argumentList.getRest()).getFirst();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            return new LispNumber(dividend.getValue().remainder(divisor.getValue()));
 | 
				
			||||||
 | 
					        } catch (ArithmeticException e) {
 | 
				
			||||||
 | 
					            throw new DivideByZeroException();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -29,6 +29,7 @@ import function.builtin.math.MINUS;
 | 
				
			|||||||
import function.builtin.math.MODULO;
 | 
					import function.builtin.math.MODULO;
 | 
				
			||||||
import function.builtin.math.MULTIPLY;
 | 
					import function.builtin.math.MULTIPLY;
 | 
				
			||||||
import function.builtin.math.PLUS;
 | 
					import function.builtin.math.PLUS;
 | 
				
			||||||
 | 
					import function.builtin.math.REMAINDER;
 | 
				
			||||||
import function.builtin.predicate.ATOM;
 | 
					import function.builtin.predicate.ATOM;
 | 
				
			||||||
import function.builtin.predicate.EQ;
 | 
					import function.builtin.predicate.EQ;
 | 
				
			||||||
import function.builtin.predicate.EQUAL;
 | 
					import function.builtin.predicate.EQUAL;
 | 
				
			||||||
@ -98,6 +99,7 @@ public class FunctionTable {
 | 
				
			|||||||
        allBuiltIns.add(PROGN.class);
 | 
					        allBuiltIns.add(PROGN.class);
 | 
				
			||||||
        allBuiltIns.add(QUOTE.class);
 | 
					        allBuiltIns.add(QUOTE.class);
 | 
				
			||||||
        allBuiltIns.add(RECUR.class);
 | 
					        allBuiltIns.add(RECUR.class);
 | 
				
			||||||
 | 
					        allBuiltIns.add(REMAINDER.class);
 | 
				
			||||||
        allBuiltIns.add(REST.class);
 | 
					        allBuiltIns.add(REST.class);
 | 
				
			||||||
        allBuiltIns.add(SET.class);
 | 
					        allBuiltIns.add(SET.class);
 | 
				
			||||||
        allBuiltIns.add(SETQ.class);
 | 
					        allBuiltIns.add(SETQ.class);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
package function.builtin.math;
 | 
					package function.builtin.math;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static testutil.TestUtilities.assertIsErrorWithMessage;
 | 
				
			||||||
import static testutil.TestUtilities.assertSExpressionsMatch;
 | 
					import static testutil.TestUtilities.assertSExpressionsMatch;
 | 
				
			||||||
import static testutil.TestUtilities.evaluateString;
 | 
					import static testutil.TestUtilities.evaluateString;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -85,17 +86,13 @@ public class MODULOTest extends SymbolAndFunctionCleaner {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test(expected = ModulusNotPositiveException.class)
 | 
					    @Test(expected = ModulusNotPositiveException.class)
 | 
				
			||||||
    public void divisorOfZero() {
 | 
					    public void negativeDivisor() {
 | 
				
			||||||
        String input = "(mod 5 0)";
 | 
					        evaluateString("(mod 5 -10)");
 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test(expected = ModulusNotPositiveException.class)
 | 
					    @Test(expected = ModulusNotPositiveException.class)
 | 
				
			||||||
    public void negativeDivisor() {
 | 
					    public void divisorOfZero() {
 | 
				
			||||||
        String input = "(mod 5 -10)";
 | 
					        evaluateString("(mod 5 0)");
 | 
				
			||||||
 | 
					 | 
				
			||||||
        assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Test(expected = BadArgumentTypeException.class)
 | 
					    @Test(expected = BadArgumentTypeException.class)
 | 
				
			||||||
@ -112,4 +109,9 @@ public class MODULOTest extends SymbolAndFunctionCleaner {
 | 
				
			|||||||
    public void modWithTooManyArguments() {
 | 
					    public void modWithTooManyArguments() {
 | 
				
			||||||
        evaluateString("(mod 1 2 3)");
 | 
					        evaluateString("(mod 1 2 3)");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void moduloNotPositiveException_HasCorrectAttributes() {
 | 
				
			||||||
 | 
					        assertIsErrorWithMessage(new ModulusNotPositiveException());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										105
									
								
								test/function/builtin/math/REMAINDERTest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								test/function/builtin/math/REMAINDERTest.java
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,105 @@
 | 
				
			|||||||
 | 
					package function.builtin.math;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static testutil.TestUtilities.assertSExpressionsMatch;
 | 
				
			||||||
 | 
					import static testutil.TestUtilities.evaluateString;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.junit.Test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import function.ArgumentValidator.BadArgumentTypeException;
 | 
				
			||||||
 | 
					import function.ArgumentValidator.TooFewArgumentsException;
 | 
				
			||||||
 | 
					import function.ArgumentValidator.TooManyArgumentsException;
 | 
				
			||||||
 | 
					import function.builtin.math.DIVIDE.DivideByZeroException;
 | 
				
			||||||
 | 
					import sexpression.LispNumber;
 | 
				
			||||||
 | 
					import testutil.SymbolAndFunctionCleaner;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class REMAINDERTest extends SymbolAndFunctionCleaner {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void rem() {
 | 
				
			||||||
 | 
					        String input = "(rem 5 3)";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(new LispNumber("2"), evaluateString(input));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void remainder() {
 | 
				
			||||||
 | 
					        String input = "(remainder 11 7)";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(new LispNumber("4"), evaluateString(input));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void dividendGreaterThanDivisor() {
 | 
				
			||||||
 | 
					        String input = "(rem 21 19)";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(new LispNumber("2"), evaluateString(input));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void dividendLessThanDivisor() {
 | 
				
			||||||
 | 
					        String input = "(rem 5 239)";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(new LispNumber("5"), evaluateString(input));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void dividendEqualToDivisor() {
 | 
				
			||||||
 | 
					        String input = "(rem 5 5)";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void dividendMultipleOfDivisor() {
 | 
				
			||||||
 | 
					        String input = "(rem 20 5)";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void divisorOfOne() {
 | 
				
			||||||
 | 
					        String input = "(rem 5 1)";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void dividendOfZero() {
 | 
				
			||||||
 | 
					        String input = "(rem 0 2309)";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test
 | 
				
			||||||
 | 
					    public void negativeDividend() {
 | 
				
			||||||
 | 
					        String input = "(rem -23 25)";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(new LispNumber("-23"), evaluateString(input));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void negativeDivisor() {
 | 
				
			||||||
 | 
					        String input = "(rem 5 -11)";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertSExpressionsMatch(new LispNumber("0"), evaluateString(input));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test(expected = DivideByZeroException.class)
 | 
				
			||||||
 | 
					    public void divisorOfZero() {
 | 
				
			||||||
 | 
					        evaluateString("(rem 5 0)");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test(expected = BadArgumentTypeException.class)
 | 
				
			||||||
 | 
					    public void remWithNonNumber() {
 | 
				
			||||||
 | 
					        evaluateString("(rem 'a 'b)");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test(expected = TooFewArgumentsException.class)
 | 
				
			||||||
 | 
					    public void remWithTooFewArguments() {
 | 
				
			||||||
 | 
					        evaluateString("(rem 1)");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Test(expected = TooManyArgumentsException.class)
 | 
				
			||||||
 | 
					    public void remWithTooManyArguments() {
 | 
				
			||||||
 | 
					        evaluateString("(rem 1 2 3)");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user