Hi, I am new to Zig, trying to port some Go code (runs in 5 seconds) but my Zig implementation is slower (7 seconds), I would appreciate hints about how to improve the performance (sample code below, attached both examples in the thread):
const std = @import("std");
const Big = std.math.big.int.Managed;
pub fn maxTotalReward(
allocator: std.mem.Allocator,
rewards: []const u32,
) !u32 {
// 1) Sort & dedupe in-place
var vals = try allocator.dupe(u32, rewards);
defer allocator.free(vals);
std.mem.sort(u32, vals, {}, comptime std.sort.asc(u32));
// Compact unique values at the front
var write: usize = 0;
for (vals) |v| {
if (write == 0 or vals[write - 1] != v) {
vals[write] = v;
write += 1;
}
}
const nums = vals[0..write];
if (nums.len == 0) return 0;
// 2) Initialize BigInts: dp=1, one=1, mask=0, temp=0
var dp = try Big.initSet(allocator, 1);
defer dp.deinit();
var one = try Big.initSet(allocator, 1);
defer one.deinit();
var mask = try Big.init(allocator);
defer mask.deinit();
var temp = try Big.init(allocator);
defer temp.deinit();
// 3) Core loop: mask = (1<<r)-1; temp = (dp & mask)<<r; dp |= temp
for (nums) |r| {
const br: usize = @intCast(r);
// mask = 1 << r
try mask.shiftLeft(&one, br);
// mask -= 1
try mask.sub(&mask, &one);
// temp = dp & mask
try temp.bitAnd(&dp, &mask);
// temp <<= r
try temp.shiftLeft(&temp, br);
// dp |= temp
try dp.bitOr(&dp, &temp);
}
// 4) Compute bit-length via base-2 string
const bin = try dp.toString(allocator, 2, .lower);
defer allocator.free(bin);
// bitLength = number of bits = string length; subtract 1 for max index
return @intCast(bin.len - 1);
}