Newer
Older
art_of_webassembly / ch03 / is_prime / is_prime.wat
@clewis clewis on 20 Mar 2024 2 KB initial commit
(module
    
    (func $even_check (param $n i32) (result i32)
        ;; returns 1 if $n is even and 0 if $n is odd
        local.get $n 
        i32.const 2
        i32.rem_u
        i32.const 0
        i32.eq          ;; $n % 2 == 0
    )

    (func $eq_2 (param $n i32) (result i32)
        local.get $n 
        i32.const 2
        i32.eq          ;; returns 1 if $n == 2
    )

    (func $multiple_check (param $n i32) (param $m i32) (result i32)
        ;; returns 1 if $n is a multiple of $m, returns 0 if it is not
        local.get $n 
        local.get $m 
        i32.rem_u       ;; get the remainder of $n / $m
        i32.const 0     ;; is the remainder equal to 0, i.e. is $n a multiple of $m
        i32.eq
    )

    (func $is_prime (export "is_prime") (param $n i32) (result i32)
        ;; return 1 if the $n is prime and 0 if $n is not
        (local $i i32)  ;; loop counter

        ;; check if $n == 1.  1 is not prime
        (if (i32.eq (local.get $n) (i32.const 1))
            (then
                i32.const 0
                return
            )
        )

        ;; check if $n == 2, which is prime
        (if (call $eq_2 (local.get $n))
            (then
                i32.const 1
                return
            )
        )

        (block $not_prime
            (call $even_check (local.get $n))
            br_if $not_prime    ;; even numbers, other than 2, are not prime

            (local.set $i (i32.const  1))
            (loop $prime_test_loop

                ;; local.tee pops $i off stack and then pushes back on stack after calculation
                (local.tee $i (i32.add (local.get $i) (i32.const 2)))  ;; i += 2
                local.get $n 

                i32.ge_u ;; $i >= $n
                if          ;; if $i >= $n, $n is prime
                    i32.const 1
                    return
                end

                (call $multiple_check (local.get $n) (local.get $i))
                br_if $not_prime    ;; if $n is a multiple of $i it is not prime
                br $prime_test_loop ;; branch back to top of loop
            ) ;; loop $prime_test_loop
        ) ;; block $not_prime

        i32.const 0         ;; return false (implicit return)
    ) ;; func $is_prime
) ;; end module