diff --git a/src/propeller/push/instructions/bool.cljc b/src/propeller/push/instructions/bool.cljc index 620fcfa..c93d645 100755 --- a/src/propeller/push/instructions/bool.cljc +++ b/src/propeller/push/instructions/bool.cljc @@ -43,7 +43,7 @@ :boolean_invert_first_then_and ^{:stacks #{:boolean}} (fn [state] - (make-instruction state #(and %1 (not %2)) [:boolean :boolean] :boolean))) + (make-instruction state #(and (not %1) %2) [:boolean :boolean] :boolean))) ;; Pushes the logical AND of the top two BOOLEANs, after applying NOT to the ;; second one @@ -51,7 +51,7 @@ :boolean_invert_second_then_and ^{:stacks #{:boolean}} (fn [state] - (make-instruction state #(and (not %1) %2) [:boolean :boolean] :boolean))) + (make-instruction state #(and %1 (not %2)) [:boolean :boolean] :boolean))) ;; Pushes FALSE if the top FLOAT is 0.0, and TRUE otherwise (def-instruction diff --git a/src/propeller/push/instructions/numeric.cljc b/src/propeller/push/instructions/numeric.cljc index b9cbf1f..2000771 100755 --- a/src/propeller/push/instructions/numeric.cljc +++ b/src/propeller/push/instructions/numeric.cljc @@ -8,7 +8,7 @@ ;; FLOAT and INTEGER Instructions (polymorphic) ;; ============================================================================= -;; Pushes TRUE onto the BOOLEAN stack if the second item is greater than the top +;; Pushes TRUE onto the BOOLEAN stack if the first item is greater than the second ;; item, and FALSE otherwise (def _gt ^{:stacks #{:boolean} @@ -65,15 +65,15 @@ #?(:clj (make-instruction state *' [stack stack] stack) :cljs (make-instruction state * [stack stack] stack)))) -;; Pushes the quotient of the top two items (i.e. the second item divided by the -;; top item) onto the same stack. If the top item is zero, pushes 1 +;; Pushes the quotient of the top two items (i.e. the first item divided by the +;; second item) onto the same stack. If the second item is zero, pushes 1 (def _quot ^{:stacks #{} :name "_quot"} (fn [stack state] (make-instruction state #(if (zero? %2) 1 (quot %1 %2)) [stack stack] stack))) -;; Pushes the second item modulo the top item onto the same stack. If the top +;; Pushes the top item modulo the second item onto the same stack. If the second ;; item is zero, pushes 1. The modulus is computed as the remainder of the ;; quotient, where the quotient has first been truncated towards negative ;; infinity. diff --git a/test/propeller/push/instructions/bool_spec.clj b/test/propeller/push/instructions/bool_spec.clj index b406a2e..163f6b4 100644 --- a/test/propeller/push/instructions/bool_spec.clj +++ b/test/propeller/push/instructions/bool_spec.clj @@ -6,7 +6,7 @@ [clojure.test.check.clojure-test :as ct :refer [defspec]] [propeller.push.state :as state] [propeller.push.instructions :as instructions] - [propeller.push.instructions.string :as string-instructions] + [propeller.push.instructions.bool :as boolean-instructions] [propeller.push.interpreter :as interpreter])) ;;boolean/and diff --git a/test/propeller/push/instructions/numeric_spec.clj b/test/propeller/push/instructions/numeric_spec.clj index 6fde2f6..09ec523 100644 --- a/test/propeller/push/instructions/numeric_spec.clj +++ b/test/propeller/push/instructions/numeric_spec.clj @@ -1,10 +1,540 @@ (ns propeller.push.instructions.numeric-spec (:require - ; [clojure.numer :as string] [clojure.test.check.generators :as gen] [clojure.test.check.properties :as prop] [clojure.test.check.clojure-test :as ct :refer [defspec]] [propeller.push.state :as state] [propeller.push.instructions :as instructions] - [propeller.push.instructions.bool :as boolean-instructions] + [propeller.tools.math :as m] + [propeller.tools.character :as c] + [propeller.push.instructions.numeric :as numeric-instructions] [propeller.push.interpreter :as interpreter])) + +(defn check-integer-gt + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :integer value1) + (state/push-to-stack :integer value2)) + end-state ((:integer_gt @instructions/instruction-table) start-state) + expected-result (> value1 value2)] + (= expected-result + (state/peek-stack end-state :boolean)))) +(defspec integer-gt-spec 100 + (prop/for-all [int1 gen/small-integer + int2 gen/small-integer] + (check-integer-gt int1 int2))) + +(defn check-float-gt + [value1 value2] + (if (or (< (m/abs value1) 0.0001) (< (m/abs value2) 0.0001)) + true + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1) + (state/push-to-stack :float value2)) + end-state ((:float_gt @instructions/instruction-table) start-state) + expected-result (> value1 value2)] + (= expected-result + (state/peek-stack end-state :boolean))))) + +(defspec float-gt-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000}) + float2 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000})] + (check-float-gt float1 float2))) + +(defn check-integer-gte + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :integer value1) + (state/push-to-stack :integer value2)) + end-state ((:integer_gte @instructions/instruction-table) start-state) + expected-result (>= value1 value2)] + (= expected-result + (state/peek-stack end-state :boolean)))) +(defspec integer-gte-spec 100 + (prop/for-all [int1 gen/small-integer + int2 gen/small-integer] + (check-integer-gte int1 int2))) + +(defn check-float-gte + [value1 value2] + (if (or (< (m/abs value1) 0.0001) (< (m/abs value2) 0.0001)) + true + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1) + (state/push-to-stack :float value2)) + end-state ((:float_gte @instructions/instruction-table) start-state) + expected-result (>= value1 value2)] + (= expected-result + (state/peek-stack end-state :boolean))))) + +(defspec float-gte-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000}) + float2 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000})] + (check-float-gte float1 float2))) + +(defn check-integer-lt + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :integer value1) + (state/push-to-stack :integer value2)) + end-state ((:integer_lt @instructions/instruction-table) start-state) + expected-result (< value1 value2)] + (= expected-result + (state/peek-stack end-state :boolean)))) + +(defspec integer-lt-spec 100 + (prop/for-all [int1 gen/small-integer + int2 gen/small-integer] + (check-integer-lt int1 int2))) + +(defn check-float-lt + [value1 value2] + (if (or (< (m/abs value1) 0.0001) (< (m/abs value2) 0.0001)) + true + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1) + (state/push-to-stack :float value2)) + end-state ((:float_lt @instructions/instruction-table) start-state) + expected-result (< value1 value2)] + (= expected-result + (state/peek-stack end-state :boolean))))) + +(defspec float-lt-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000}) + float2 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000})] + (check-float-lt float1 float2))) + + +(defn check-integer-lte + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :integer value1) + (state/push-to-stack :integer value2)) + end-state ((:integer_lte @instructions/instruction-table) start-state) + expected-result (<= value1 value2)] + (= expected-result + (state/peek-stack end-state :boolean)))) + +(defspec integer-lte-spec 100 + (prop/for-all [int1 gen/small-integer + int2 gen/small-integer] + (check-integer-lte int1 int2))) + + +(defn check-float-lte + [value1 value2] + (if (or (< (m/abs value1) 0.0001) (< (m/abs value2) 0.0001)) + true + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1) + (state/push-to-stack :float value2)) + end-state ((:float_lte @instructions/instruction-table) start-state) + expected-result (<= value1 value2)] + (= expected-result + (state/peek-stack end-state :boolean))))) + +(defspec float-lte-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000}) + float2 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000})] + (check-float-lte float1 float2))) + +(defn check-integer-add + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :integer value1) + (state/push-to-stack :integer value2)) + end-state ((:integer_add @instructions/instruction-table) start-state) + expected-result (+ value1 value2)] + (= expected-result + (state/peek-stack end-state :integer)))) +(defspec integer-add-spec 100 + (prop/for-all [int1 gen/small-integer + int2 gen/small-integer] + (check-integer-add int1 int2))) + +(defn check-float-add + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1) + (state/push-to-stack :float value2)) + end-state ((:float_add @instructions/instruction-table) start-state) + expected-result (+ value1 value2)] + (m/approx= expected-result + (state/peek-stack end-state :float) 0.0001))) + +(defspec float-add-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min (/ -1000000 2), :max (/ 1000000 2)}) + float2 (gen/double* {:infinite? false, :NaN? false, :min (/ -1000000 2), :max (/ 1000000 2)})] + (check-float-add float1 float2))) + + +(defn check-integer-subtract + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :integer value1) + (state/push-to-stack :integer value2)) + end-state ((:integer_subtract @instructions/instruction-table) start-state) + expected-result (- value1 value2)] + (= expected-result + (state/peek-stack end-state :integer)))) + +(defspec integer-subtract-spec 100 + (prop/for-all [int1 gen/small-integer + int2 gen/small-integer] + (check-integer-subtract int1 int2))) + +(defn check-float-subtract + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1) + (state/push-to-stack :float value2)) + end-state ((:float_subtract @instructions/instruction-table) start-state) + expected-result (- value1 value2)] + (m/approx= expected-result + (state/peek-stack end-state :float) 0.0001))) + +(defspec float-subtract-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min (/ -1000000 2), :max (/ 1000000 2)}) + float2 (gen/double* {:infinite? false, :NaN? false, :min (/ -1000000 2), :max (/ 1000000 2)})] + (check-float-subtract float1 float2))) + +(defn check-integer-mult + [value1 value2] + (if (or (< (m/abs value1) 0.00001) (< (m/abs value2) 0.00001)) + true + (let [start-state (-> state/empty-state + (state/push-to-stack :integer value1) + (state/push-to-stack :integer value2)) + end-state ((:integer_mult @instructions/instruction-table) start-state) + expected-result (* value1 value2)] + (= expected-result + (state/peek-stack end-state :integer))))) + +(defspec integer-mult-spec 100 + (prop/for-all [int1 gen/small-integer + int2 gen/small-integer] + (check-integer-mult int1 int2))) + + +(defn check-float-mult + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1) + (state/push-to-stack :float value2)) + end-state ((:float_mult @instructions/instruction-table) start-state) + expected-result (* value1 value2)] + (m/approx= expected-result + (state/peek-stack end-state :float) 0.0001))) + +(defspec float-mult-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min (* -1 (m/sqrt 1000000)), :max (m/sqrt 1000000)}) + float2 (gen/double* {:infinite? false, :NaN? false, :min (* -1 (m/sqrt 1000000)), :max (m/sqrt 1000000)})] + (check-float-mult float1 float2))) + +(defn check-integer-quot + [value1 value2] + (if (= value2 0) + true + (let [start-state (-> state/empty-state + (state/push-to-stack :integer value1) + (state/push-to-stack :integer value2)) + end-state ((:integer_quot @instructions/instruction-table) start-state) + expected-result (quot value1 value2)] + (= expected-result + (state/peek-stack end-state :integer ))))) + +(defspec integer-quot-spec 100 + (prop/for-all [int1 gen/small-integer + int2 gen/small-integer] + (check-integer-quot int1 int2))) + +(defn check-float-quot + [value1 value2] + (if (= value2 0.0) + true + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1) + (state/push-to-stack :float value2)) + end-state ((:float_quot @instructions/instruction-table) start-state) + expected-result (quot value1 value2)] + (= expected-result + (state/peek-stack end-state :float))))) + +(defspec float-quot-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000}) + float2 (gen/double* {:infinite? false, :NaN? false, :min 1.0, :max 1000000})] + (check-float-quot float1 float2))) + +(defn check-integer-mod + [value1 value2] + (if (= value2 0) + true + (let [start-state (-> state/empty-state + (state/push-to-stack :integer value1) + (state/push-to-stack :integer value2)) + end-state ((:integer_mod @instructions/instruction-table) start-state) + expected-result (mod value1 value2)] + (= expected-result + (state/peek-stack end-state :integer))))) + +(defspec integer-mod-spec 100 + (prop/for-all [int1 gen/small-integer + int2 gen/small-integer] + (check-integer-mod int1 int2))) + +(defn check-float-mod + [value1 value2] + (if (m/approx= value1 0.0 0.00001) + true + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1) + (state/push-to-stack :float value2)) + end-state ((:float_mod @instructions/instruction-table) start-state) + expected-result (mod value1 value2)] + (m/approx= expected-result + (state/peek-stack end-state :float) 0.001)))) + + +(defspec float-mod-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000}) + float2 (gen/double* {:infinite? false, :NaN? false, :min 1.0, :max 1000000})] + (check-float-mod float1 float2))) +(defn check-integer-max + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :integer value1) + (state/push-to-stack :integer value2)) + end-state ((:integer_max @instructions/instruction-table) start-state) + expected-result (max value2 value1)] + (= expected-result + (state/peek-stack end-state :integer)))) + +(defspec integer-max-spec 100 + (prop/for-all [int1 gen/small-integer + int2 gen/small-integer] + (check-integer-max int1 int2))) + +(defn check-float-max + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1) + (state/push-to-stack :float value2)) + end-state ((:float_max @instructions/instruction-table) start-state) + expected-result (max value1 value2)] + (m/approx= expected-result + (state/peek-stack end-state :float) 0.0001))) + +(defspec float-max-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000}) + float2 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000})] + (check-float-max float1 float2))) + +(defn check-integer-min + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :integer value1) + (state/push-to-stack :integer value2)) + end-state ((:integer_min @instructions/instruction-table) start-state) + expected-result (min value2 value1)] + (= expected-result + (state/peek-stack end-state :integer)))) + +(defspec integer-min-spec 100 + (prop/for-all [int1 gen/small-integer + int2 gen/small-integer] + (check-integer-min int1 int2))) +(defn check-float-min + [value1 value2] + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1) + (state/push-to-stack :float value2)) + end-state ((:float_min @instructions/instruction-table) start-state) + expected-result (min value1 value2)] + (m/approx= expected-result + (state/peek-stack end-state :float) 0.0001))) + +(defspec float-min-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000}) + float2 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000})] + (check-float-min float1 float2))) + +(defn check-integer-from-boolean + [value1] + (let [start-state (-> state/empty-state + (state/push-to-stack :boolean value1)) + end-state ((:integer_from_boolean @instructions/instruction-table) start-state) + expected-result (if value1 + 1 + 0)] + (= expected-result + (state/peek-stack end-state :integer)))) + +(defspec integer-from-boolean-spec 100 + (prop/for-all [bool1 gen/boolean] + (check-integer-from-boolean bool1))) + +(defn check-float-from-boolean + [value1] + (let [start-state (-> state/empty-state + (state/push-to-stack :boolean value1)) + end-state ((:float_from_boolean @instructions/instruction-table) start-state) + expected-result (if value1 + 1.0 + 0.0)] + (= expected-result + (state/peek-stack end-state :float)))) + +(defspec float-from-boolean-spec 100 + (prop/for-all [bool1 gen/boolean] + (check-float-from-boolean bool1))) + + +(defn check-integer-from-char + [value1] + (let [start-state (-> state/empty-state + (state/push-to-stack :char value1)) + end-state ((:integer_from_char @instructions/instruction-table) start-state) + expected-result (c/get-ascii value1)] + (= expected-result + (state/peek-stack end-state :integer)))) + +(defspec integer-from-char-spec 100 + (prop/for-all [char1 gen/char] + (check-integer-from-char char1))) + +;(defn check-float-from-char +; [value1] +; (let [start-state (-> state/empty-state +; (state/push-to-stack :char value1)) +; end-state ((:float_from_char @instructions/instruction-table) start-state) +; expected-result (float (c/get-ascii value1))] +; (= expected-result +; (state/peek-stack end-state :char)))) +;(println (check-float-from-char (first "abc"))) +; +;(defspec float-from-char-spec 100 +; (prop/for-all [char1 gen/char] +; (check-float-from-char char1))) + + +;;;FROM STRING NEEDED + +(defn check-integer-inc + [value1] + (let [start-state (-> state/empty-state + (state/push-to-stack :integer value1)) + end-state ((:integer_inc @instructions/instruction-table) start-state) + expected-result (+ value1 1)] + (= expected-result + (state/peek-stack end-state :integer)))) + +(defspec integer-inc-spec 100 + (prop/for-all [int1 gen/small-integer] + (check-integer-inc int1))) + +(defn check-float-inc + [value1] + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1)) + end-state ((:float_inc @instructions/instruction-table) start-state) + expected-result (+ value1 1.0)] + (m/approx= expected-result + (state/peek-stack end-state :float) 0.0001))) + +(defspec float-inc-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 999999})] + (check-float-inc float1))) + +(defn check-integer-dec + [value1] + (let [start-state (-> state/empty-state + (state/push-to-stack :integer value1)) + end-state ((:integer_dec @instructions/instruction-table) start-state) + expected-result (- value1 1)] + (= expected-result + (state/peek-stack end-state :integer)))) + +(defspec integer-dec-spec 100 + (prop/for-all [int1 gen/small-integer] + (check-integer-dec int1))) + +(defn check-float-dec + [value1] + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1)) + end-state ((:float_dec @instructions/instruction-table) start-state) + expected-result (- value1 1.0)] + (m/approx= expected-result + (state/peek-stack end-state :float) 0.0001))) + +(defspec float-dec-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min -999999, :max 1000000})] + (check-float-dec float1))) + + +(defn check-float-cos + [value1] + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1)) + end-state ((:float_cos @instructions/instruction-table) start-state) + expected-result (m/cos value1)] + (m/approx= expected-result + (state/peek-stack end-state :float) 0.001))) + +(defspec float-cos-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000})] + (check-float-cos float1))) + +(defn check-float-sin + [value1] + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1)) + end-state ((:float_sin @instructions/instruction-table) start-state) + expected-result (m/sin value1)] + (m/approx= expected-result + (state/peek-stack end-state :float) 0.001))) + +(defspec float-sin-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000})] + (check-float-sin float1))) + +(defn check-float-tan + [value1] + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1)) + end-state ((:float_tan @instructions/instruction-table) start-state) + expected-result (m/tan value1)] + (m/approx= expected-result + (state/peek-stack end-state :float) 0.001))) + +(defspec float-tan-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000})] + (check-float-tan float1))) + + +(defn check-float-from-integer + [value1] + (let [start-state (-> state/empty-state + (state/push-to-stack :integer value1)) + end-state ((:float_from_integer @instructions/instruction-table) start-state) + expected-result (float value1)] + (= expected-result + (state/peek-stack end-state :float)))) + +(defspec float-from-integer-spec 100 + (prop/for-all [int1 gen/small-integer] + (check-float-from-integer int1))) + +(defn check-integer-from-float + [value1] + (let [start-state (-> state/empty-state + (state/push-to-stack :float value1)) + end-state ((:integer_from_float @instructions/instruction-table) start-state) + expected-result (int value1)] + (= expected-result + (state/peek-stack end-state :integer)))) + +(defspec integer-from-float-spec 100 + (prop/for-all [float1 (gen/double* {:infinite? false, :NaN? false, :min -1000000, :max 1000000})] + (check-integer-from-float float1))) +