const ct_protected = struct fn select(on: bool, x: Limb, y: Limb) LimbReturns x if on is true, otherwise y.
fn eql(x: anytype, y: @TypeOf(x)) boolCompares two values in constant time.
fn limbsCmpLt(x: anytype, y: @TypeOf(x)) boolCompares two big integers in constant time, returning true if x < y.
fn limbsCmpGeq(x: anytype, y: @TypeOf(x)) boolCompares two big integers in constant time, returning true if x >= y.
fn mulWide(x: Limb, y: Limb) WideLimbMultiplies two limbs and returns the result as a wide limb.
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924const ct_protected = struct {
// Returns x if on is true, otherwise y.
fn select(on: bool, x: Limb, y: Limb) Limb {
const mask = @as(Limb, 0) -% @intFromBool(on);
return y ^ (mask & (y ^ x));
}
// Compares two values in constant time.
fn eql(x: anytype, y: @TypeOf(x)) bool {
const c1 = @subWithOverflow(x, y)[1];
const c2 = @subWithOverflow(y, x)[1];
return @as(bool, @bitCast(1 - (c1 | c2)));
}
// Compares two big integers in constant time, returning true if x < y.
fn limbsCmpLt(x: anytype, y: @TypeOf(x)) bool {
var c: u1 = 0;
for (x.limbsConst(), y.limbsConst()) |x_limb, y_limb| {
c = @truncate((x_limb -% y_limb -% c) >> t_bits);
}
return c != 0;
}
// Compares two big integers in constant time, returning true if x >= y.
fn limbsCmpGeq(x: anytype, y: @TypeOf(x)) bool {
return !limbsCmpLt(x, y);
}
// Multiplies two limbs and returns the result as a wide limb.
fn mulWide(x: Limb, y: Limb) WideLimb {
const half_bits = @typeInfo(Limb).int.bits / 2;
const Half = @Int(.unsigned, half_bits);
const x0 = @as(Half, @truncate(x));
const x1 = @as(Half, @truncate(x >> half_bits));
const y0 = @as(Half, @truncate(y));
const y1 = @as(Half, @truncate(y >> half_bits));
const w0 = math.mulWide(Half, x0, y0);
const t = math.mulWide(Half, x1, y0) + (w0 >> half_bits);
var w1: Limb = @as(Half, @truncate(t));
const w2 = @as(Half, @truncate(t >> half_bits));
w1 += math.mulWide(Half, x0, y1);
const hi = math.mulWide(Half, x1, y1) + w2 + (w1 >> half_bits);
const lo = x *% y;
return .{ .hi = hi, .lo = lo };
}
}