Browse Source

Added Math.gcf() and Math.lcm()

Steven Hall 8 years ago
parent
commit
ece9659fe2
3 changed files with 79 additions and 0 deletions
  1. 55 0
      src/optionals/gravity_math.c
  2. 12 0
      test/unittest/math/gcf.gravity
  3. 12 0
      test/unittest/math/lcm.gravity

+ 55 - 0
src/optionals/gravity_math.c

@@ -306,6 +306,59 @@ static bool math_floor (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, u
     RETURN_VALUE(VALUE_FROM_UNDEFINED, rindex);
 }
 
+static int gcf(int x, int y) {
+    if (x == 0) {
+        return y;
+    }
+    while (y != 0) {
+        if (x > y) {
+            x = x - y;
+        }
+        else {
+            y = y - x;
+        }
+    }
+    return x;
+}
+
+static bool math_gcf (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
+    #pragma unused (vm, rindex)
+    if (nargs < 3) RETURN_VALUE(VALUE_FROM_UNDEFINED, rindex);
+
+    for (int i = 1; i < nargs; ++i) {
+        if (!VALUE_ISA_INT(GET_VALUE(i))) RETURN_VALUE(VALUE_FROM_UNDEFINED, rindex);
+    }
+
+    int gcf_value = (int)GET_VALUE(1).n;
+
+    for (int i = 1; i < nargs-1; ++i) {
+        gcf_value = gcf(gcf_value, (int)GET_VALUE(i+1).n);
+    }
+
+    RETURN_VALUE(VALUE_FROM_INT(gcf_value), rindex);
+}
+
+static int lcm(int x, int y) {
+    return x*y/gcf(x,y);
+}
+
+static bool math_lcm (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
+    #pragma unused (vm, rindex)
+    if (nargs < 3) RETURN_ERROR("2 or more arguments expected");
+
+    for (int i = 1; i < nargs; ++i) {
+        if (!VALUE_ISA_INT(GET_VALUE(i))) RETURN_VALUE(VALUE_FROM_UNDEFINED, rindex);
+    }
+
+    int lcm_value = (int)GET_VALUE(1).n;
+
+    for (int i = 1; i < nargs-1; ++i) {
+        lcm_value = lcm(lcm_value, (int)GET_VALUE(i+1).n);
+    }
+
+    RETURN_VALUE(VALUE_FROM_INT(lcm_value), rindex);
+}
+
 // returns the natural logarithm (base E) of x
 static bool math_log (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
     #pragma unused(vm, nargs)
@@ -567,6 +620,8 @@ static void create_optional_class (void) {
     gravity_class_bind(meta, "cos", NEW_CLOSURE_VALUE(math_cos));
     gravity_class_bind(meta, "exp", NEW_CLOSURE_VALUE(math_exp));
     gravity_class_bind(meta, "floor", NEW_CLOSURE_VALUE(math_floor));
+    gravity_class_bind(meta, "gcf", NEW_CLOSURE_VALUE(math_gcf));
+    gravity_class_bind(meta, "lcm", NEW_CLOSURE_VALUE(math_lcm));
     gravity_class_bind(meta, "log", NEW_CLOSURE_VALUE(math_log));
     gravity_class_bind(meta, "max", NEW_CLOSURE_VALUE(math_max));
     gravity_class_bind(meta, "min", NEW_CLOSURE_VALUE(math_min));

+ 12 - 0
test/unittest/math/gcf.gravity

@@ -0,0 +1,12 @@
+#unittest {
+	name: "Test Math.gcf()";
+	error: NONE;
+	result: true;
+};
+
+func main() {
+	var r1 = Math.gcf(10, 1) == 1
+	var r2 = Math.gcf(10, 10) == 10
+	var r3 = Math.gcf(12, 15, 21) == 3
+	return r1 and r2 and r3
+}

+ 12 - 0
test/unittest/math/lcm.gravity

@@ -0,0 +1,12 @@
+#unittest {
+	name: "Test Math.lcm()";
+	error: NONE;
+	result: true;
+};
+
+func main() {
+	var r1 = Math.lcm(10, 1) == 10
+	var r2 = Math.lcm(3, 4) == 12
+	var r3 = Math.lcm(6, 15, 2) == 30
+	return r1 and r2 and r3
+}