const std = @import("std");
const math = std.math;
pub fn main() !void {
const stdout_file = std.io.getStdOut().writer();
var bw = std.io.bufferedWriter(stdout_file);
const stdout = bw.writer();
const n: i32 = 111181111;
try stdout.print("{} is prime? {}.\n", .{ n, is_prime(n) });
try bw.flush(); // don't forget to flush!
}
fn is_prime(n: i32) bool {
var i: i32 = 2;
const f: f64 = @floatFromInt(n);
const floor: i32 = @intFromFloat(math.floor(math.sqrt(f)));
while (i <= floor) {
if (@mod(n, i) == 0) {
return false;
}
i += 1;
}
return true;
}
fn is_prime1(n: i32) bool {
var i: i32 = 2;
const f: f64 = @floatFromInt(n);
const floor: i32 = @intFromFloat(math.floor(math.sqrt(f)));
_ = floor;
while (i < n) {
if (@mod(n, i) == 0) {
return false;
}
i += 1;
}
return true;
}
I don’t know why is_prime() is much slower than is_prime1(), both in debug mode and ReleaseFast mode.In stead, I think is_prime() should have higher performance than is_prime1().
For me is_prime is a lot faster than is_prime1. is_prime took less than 1 ms for the given prime number.
I suspect that you made a measuring error. Is it possible that you timed the compile time as well?
For example running time zig run test.zig will measure the compile+execution time. And with the given number the execution time is actually a lot faster than the compile time.
In general I would suggest only benachmarking the part of the code that you actually care about. This ensures that you don’t measure any weird side effects:
Now there is one other effect here. Note that @mod is not equivalent to % in other languages. It behaves differently for negative numbers. And since @mod is usually not implemented on the hardware directly(*except from powers of 2), you will loose some performance(unless the compiler figures out that your inputs are positive).
I measured a ~2× performance improvement when replacing @mod with @rem or when using u32 instead of i32.