mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
stage2: implement @popCount for non-vectors
This commit is contained in:
parent
5ff01bd820
commit
d6067db062
@ -733,6 +733,27 @@ pub const Mutable = struct {
|
|||||||
rma.truncate(rma.toConst(), signedness, bit_count);
|
rma.truncate(rma.toConst(), signedness, bit_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// r = @popCount(a) with 2s-complement semantics.
|
||||||
|
/// r and a may be aliases.
|
||||||
|
///
|
||||||
|
/// Assets the result fits in `r`. Upper bound on the number of limbs needed by
|
||||||
|
/// r is `calcTwosCompLimbCount(bit_count)`.
|
||||||
|
pub fn popCount(r: *Mutable, a: Const, bit_count: usize) void {
|
||||||
|
r.copy(a);
|
||||||
|
|
||||||
|
if (!a.positive) {
|
||||||
|
r.positive = true; // Negate.
|
||||||
|
r.bitNotWrap(r.toConst(), .unsigned, bit_count); // Bitwise NOT.
|
||||||
|
r.addScalar(r.toConst(), 1); // Add one.
|
||||||
|
}
|
||||||
|
|
||||||
|
var sum: Limb = 0;
|
||||||
|
for (r.limbs[0..r.len]) |limb| {
|
||||||
|
sum += @popCount(Limb, limb);
|
||||||
|
}
|
||||||
|
r.set(sum);
|
||||||
|
}
|
||||||
|
|
||||||
/// rma = a * a
|
/// rma = a * a
|
||||||
///
|
///
|
||||||
/// `rma` may not alias with `a`.
|
/// `rma` may not alias with `a`.
|
||||||
@ -2735,6 +2756,15 @@ pub const Managed = struct {
|
|||||||
m.saturate(a, signedness, bit_count);
|
m.saturate(a, signedness, bit_count);
|
||||||
r.setMetadata(m.positive, m.len);
|
r.setMetadata(m.positive, m.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// r = @popCount(a) with 2s-complement semantics.
|
||||||
|
/// r and a may be aliases.
|
||||||
|
pub fn popCount(r: *Managed, a: Const, bit_count: usize) !void {
|
||||||
|
try r.ensureCapacity(calcTwosCompLimbCount(bit_count));
|
||||||
|
var m = r.toMutable();
|
||||||
|
m.popCount(a, bit_count);
|
||||||
|
r.setMetadata(m.positive, m.len);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Different operators which can be used in accumulation style functions
|
/// Different operators which can be used in accumulation style functions
|
||||||
|
|||||||
@ -2434,3 +2434,14 @@ test "big.int regression test for realloc with alias" {
|
|||||||
|
|
||||||
try testing.expect(a.toConst().orderAgainstScalar(14691098406862188148944207245954912110548093601382197697835) == .eq);
|
try testing.expect(a.toConst().orderAgainstScalar(14691098406862188148944207245954912110548093601382197697835) == .eq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "big int popcount" {
|
||||||
|
var a = try Managed.initSet(testing.allocator, -1);
|
||||||
|
defer a.deinit();
|
||||||
|
var b = try Managed.initSet(testing.allocator, -1);
|
||||||
|
defer b.deinit();
|
||||||
|
|
||||||
|
try a.popCount(b.toConst(), 16);
|
||||||
|
|
||||||
|
try testing.expect(a.toConst().orderAgainstScalar(16) == .eq);
|
||||||
|
}
|
||||||
|
|||||||
@ -202,6 +202,10 @@ pub const Inst = struct {
|
|||||||
/// Result type will always be an unsigned integer big enough to fit the answer.
|
/// Result type will always be an unsigned integer big enough to fit the answer.
|
||||||
/// Uses the `ty_op` field.
|
/// Uses the `ty_op` field.
|
||||||
ctz,
|
ctz,
|
||||||
|
/// Count number of 1 bits in an integer according to its representation in twos complement.
|
||||||
|
/// Result type will always be an unsigned integer big enough to fit the answer.
|
||||||
|
/// Uses the `ty_op` field.
|
||||||
|
popcount,
|
||||||
|
|
||||||
/// `<`. Result type is always bool.
|
/// `<`. Result type is always bool.
|
||||||
/// Uses the `bin_op` field.
|
/// Uses the `bin_op` field.
|
||||||
@ -744,6 +748,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
|||||||
.get_union_tag,
|
.get_union_tag,
|
||||||
.clz,
|
.clz,
|
||||||
.ctz,
|
.ctz,
|
||||||
|
.popcount,
|
||||||
=> return air.getRefType(datas[inst].ty_op.ty),
|
=> return air.getRefType(datas[inst].ty_op.ty),
|
||||||
|
|
||||||
.loop,
|
.loop,
|
||||||
|
|||||||
@ -313,6 +313,7 @@ fn analyzeInst(
|
|||||||
.get_union_tag,
|
.get_union_tag,
|
||||||
.clz,
|
.clz,
|
||||||
.ctz,
|
.ctz,
|
||||||
|
.popcount,
|
||||||
=> {
|
=> {
|
||||||
const o = inst_datas[inst].ty_op;
|
const o = inst_datas[inst].ty_op;
|
||||||
return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none });
|
return trackOperands(a, new_set, inst, main_tomb, .{ o.operand, .none, .none });
|
||||||
|
|||||||
26
src/Sema.zig
26
src/Sema.zig
@ -9904,8 +9904,30 @@ fn zirCtz(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
|
|||||||
|
|
||||||
fn zirPopCount(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
fn zirPopCount(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||||
const src = inst_data.src();
|
const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||||
return sema.fail(block, src, "TODO: Sema.zirPopCount", .{});
|
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
|
||||||
|
const operand = sema.resolveInst(inst_data.operand);
|
||||||
|
const operand_ty = sema.typeOf(operand);
|
||||||
|
// TODO implement support for vectors
|
||||||
|
if (operand_ty.zigTypeTag() != .Int) {
|
||||||
|
return sema.fail(block, ty_src, "expected integer type, found '{}'", .{
|
||||||
|
operand_ty,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const target = sema.mod.getTarget();
|
||||||
|
const bits = operand_ty.intInfo(target).bits;
|
||||||
|
if (bits == 0) return Air.Inst.Ref.zero;
|
||||||
|
|
||||||
|
const result_ty = try Type.smallestUnsignedInt(sema.arena, bits);
|
||||||
|
|
||||||
|
const runtime_src = if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
|
||||||
|
if (val.isUndef()) return sema.addConstUndef(result_ty);
|
||||||
|
const result_val = try val.popCount(operand_ty, target, sema.arena);
|
||||||
|
return sema.addConstant(result_ty, result_val);
|
||||||
|
} else operand_src;
|
||||||
|
|
||||||
|
try sema.requireRuntimeBlock(block, runtime_src);
|
||||||
|
return block.addTyOp(.popcount, result_ty, operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||||
|
|||||||
@ -481,6 +481,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
|||||||
.get_union_tag => try self.airGetUnionTag(inst),
|
.get_union_tag => try self.airGetUnionTag(inst),
|
||||||
.clz => try self.airClz(inst),
|
.clz => try self.airClz(inst),
|
||||||
.ctz => try self.airCtz(inst),
|
.ctz => try self.airCtz(inst),
|
||||||
|
.popcount => try self.airPopcount(inst),
|
||||||
|
|
||||||
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
|
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
|
||||||
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
|
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
|
||||||
@ -1138,6 +1139,12 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
|
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||||
|
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airPopcount for {}", .{self.target.cpu.arch});
|
||||||
|
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||||
|
}
|
||||||
|
|
||||||
fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
|
fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
|
||||||
if (!self.liveness.operandDies(inst, op_index))
|
if (!self.liveness.operandDies(inst, op_index))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -836,6 +836,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||||||
.get_union_tag => try self.airGetUnionTag(inst),
|
.get_union_tag => try self.airGetUnionTag(inst),
|
||||||
.clz => try self.airClz(inst),
|
.clz => try self.airClz(inst),
|
||||||
.ctz => try self.airCtz(inst),
|
.ctz => try self.airCtz(inst),
|
||||||
|
.popcount => try self.airPopcount(inst),
|
||||||
|
|
||||||
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
|
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
|
||||||
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
|
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
|
||||||
@ -1610,6 +1611,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
|||||||
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
|
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||||
|
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (arch) {
|
||||||
|
else => return self.fail("TODO implement airPopcount for {}", .{self.target.cpu.arch}),
|
||||||
|
};
|
||||||
|
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||||
|
}
|
||||||
|
|
||||||
fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
|
fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool {
|
||||||
if (!self.liveness.operandDies(inst, op_index))
|
if (!self.liveness.operandDies(inst, op_index))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -1107,6 +1107,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
|
|||||||
.get_union_tag => try airGetUnionTag(f, inst),
|
.get_union_tag => try airGetUnionTag(f, inst),
|
||||||
.clz => try airBuiltinCall(f, inst, "clz"),
|
.clz => try airBuiltinCall(f, inst, "clz"),
|
||||||
.ctz => try airBuiltinCall(f, inst, "ctz"),
|
.ctz => try airBuiltinCall(f, inst, "ctz"),
|
||||||
|
.popcount => try airBuiltinCall(f, inst, "popcount"),
|
||||||
|
|
||||||
.int_to_float,
|
.int_to_float,
|
||||||
.float_to_int,
|
.float_to_int,
|
||||||
|
|||||||
@ -1777,6 +1777,7 @@ pub const FuncGen = struct {
|
|||||||
.get_union_tag => try self.airGetUnionTag(inst),
|
.get_union_tag => try self.airGetUnionTag(inst),
|
||||||
.clz => try self.airClzCtz(inst, "ctlz"),
|
.clz => try self.airClzCtz(inst, "ctlz"),
|
||||||
.ctz => try self.airClzCtz(inst, "cttz"),
|
.ctz => try self.airClzCtz(inst, "cttz"),
|
||||||
|
.popcount => try self.airPopCount(inst, "ctpop"),
|
||||||
|
|
||||||
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
|
.atomic_store_unordered => try self.airAtomicStore(inst, .Unordered),
|
||||||
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
|
.atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic),
|
||||||
@ -3679,6 +3680,40 @@ pub const FuncGen = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn airPopCount(self: *FuncGen, inst: Air.Inst.Index, prefix: [*:0]const u8) !?*const llvm.Value {
|
||||||
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
|
||||||
|
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||||
|
const operand_ty = self.air.typeOf(ty_op.operand);
|
||||||
|
const operand = try self.resolveInst(ty_op.operand);
|
||||||
|
const target = self.dg.module.getTarget();
|
||||||
|
const bits = operand_ty.intInfo(target).bits;
|
||||||
|
|
||||||
|
var fn_name_buf: [100]u8 = undefined;
|
||||||
|
const llvm_fn_name = std.fmt.bufPrintZ(&fn_name_buf, "llvm.{s}.i{d}", .{
|
||||||
|
prefix, bits,
|
||||||
|
}) catch unreachable;
|
||||||
|
const fn_val = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: {
|
||||||
|
const operand_llvm_ty = try self.dg.llvmType(operand_ty);
|
||||||
|
const param_types = [_]*const llvm.Type{operand_llvm_ty};
|
||||||
|
const fn_type = llvm.functionType(operand_llvm_ty, ¶m_types, param_types.len, .False);
|
||||||
|
break :blk self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type);
|
||||||
|
};
|
||||||
|
|
||||||
|
const params = [_]*const llvm.Value{operand};
|
||||||
|
const wrong_size_result = self.builder.buildCall(fn_val, ¶ms, params.len, .C, .Auto, "");
|
||||||
|
const result_ty = self.air.typeOfIndex(inst);
|
||||||
|
const result_llvm_ty = try self.dg.llvmType(result_ty);
|
||||||
|
const result_bits = result_ty.intInfo(target).bits;
|
||||||
|
if (bits > result_bits) {
|
||||||
|
return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");
|
||||||
|
} else if (bits < result_bits) {
|
||||||
|
return self.builder.buildZExt(wrong_size_result, result_llvm_ty, "");
|
||||||
|
} else {
|
||||||
|
return wrong_size_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn callFloor(self: *FuncGen, arg: *const llvm.Value, ty: Type) !*const llvm.Value {
|
fn callFloor(self: *FuncGen, arg: *const llvm.Value, ty: Type) !*const llvm.Value {
|
||||||
return self.callFloatUnary(arg, ty, "floor");
|
return self.callFloatUnary(arg, ty, "floor");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -196,6 +196,7 @@ const Writer = struct {
|
|||||||
.get_union_tag,
|
.get_union_tag,
|
||||||
.clz,
|
.clz,
|
||||||
.ctz,
|
.ctz,
|
||||||
|
.popcount,
|
||||||
=> try w.writeTyOp(s, inst),
|
=> try w.writeTyOp(s, inst),
|
||||||
|
|
||||||
.block,
|
.block,
|
||||||
|
|||||||
216
src/value.zig
216
src/value.zig
@ -1062,14 +1062,7 @@ pub const Value = extern union {
|
|||||||
const limbs_buffer = try arena.alloc(std.math.big.Limb, 2);
|
const limbs_buffer = try arena.alloc(std.math.big.Limb, 2);
|
||||||
var bigint = BigIntMutable.init(limbs_buffer, 0);
|
var bigint = BigIntMutable.init(limbs_buffer, 0);
|
||||||
bigint.readTwosComplement(buffer, int_info.bits, endian, int_info.signedness);
|
bigint.readTwosComplement(buffer, int_info.bits, endian, int_info.signedness);
|
||||||
// TODO if it fits in 64 bits then use one of those tags
|
return fromBigInt(arena, bigint.toConst());
|
||||||
|
|
||||||
const result_limbs = bigint.limbs[0..bigint.len];
|
|
||||||
if (bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(arena, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(arena, result_limbs);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
.Float => switch (ty.floatBits(target)) {
|
.Float => switch (ty.floatBits(target)) {
|
||||||
16 => return Value.Tag.float_16.create(arena, floatReadFromMemory(f16, target, buffer)),
|
16 => return Value.Tag.float_16.create(arena, floatReadFromMemory(f16, target, buffer)),
|
||||||
@ -1200,16 +1193,34 @@ pub const Value = extern union {
|
|||||||
if (x == 0) return 0;
|
if (x == 0) return 0;
|
||||||
return @intCast(usize, std.math.log2(x) + 1);
|
return @intCast(usize, std.math.log2(x) + 1);
|
||||||
},
|
},
|
||||||
.int_i64 => {
|
|
||||||
@panic("TODO implement i64 intBitCountTwosComp");
|
|
||||||
},
|
|
||||||
.int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().bitCountTwosComp(),
|
.int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().bitCountTwosComp(),
|
||||||
.int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().bitCountTwosComp(),
|
.int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().bitCountTwosComp(),
|
||||||
|
|
||||||
else => unreachable,
|
else => {
|
||||||
|
var buffer: BigIntSpace = undefined;
|
||||||
|
return self.toBigInt(&buffer).bitCountTwosComp();
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn popCount(val: Value, ty: Type, target: Target, arena: *Allocator) !Value {
|
||||||
|
assert(!val.isUndef());
|
||||||
|
|
||||||
|
const info = ty.intInfo(target);
|
||||||
|
|
||||||
|
var buffer: Value.BigIntSpace = undefined;
|
||||||
|
const operand_bigint = val.toBigInt(&buffer);
|
||||||
|
|
||||||
|
const limbs = try arena.alloc(
|
||||||
|
std.math.big.Limb,
|
||||||
|
std.math.big.int.calcTwosCompLimbCount(info.bits),
|
||||||
|
);
|
||||||
|
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||||
|
result_bigint.popCount(operand_bigint, info.bits);
|
||||||
|
|
||||||
|
return fromBigInt(arena, result_bigint.toConst());
|
||||||
|
}
|
||||||
|
|
||||||
/// Asserts the value is an integer, and the destination type is ComptimeInt or Int.
|
/// Asserts the value is an integer, and the destination type is ComptimeInt or Int.
|
||||||
pub fn intFitsInType(self: Value, ty: Type, target: Target) bool {
|
pub fn intFitsInType(self: Value, ty: Type, target: Target) bool {
|
||||||
switch (self.tag()) {
|
switch (self.tag()) {
|
||||||
@ -1246,7 +1257,8 @@ pub const Value = extern union {
|
|||||||
const info = ty.intInfo(target);
|
const info = ty.intInfo(target);
|
||||||
if (info.signedness == .unsigned and x < 0)
|
if (info.signedness == .unsigned and x < 0)
|
||||||
return false;
|
return false;
|
||||||
@panic("TODO implement i64 intFitsInType");
|
var buffer: BigIntSpace = undefined;
|
||||||
|
return self.toBigInt(&buffer).fitsInTwosComp(info.signedness, info.bits);
|
||||||
},
|
},
|
||||||
.ComptimeInt => return true,
|
.ComptimeInt => return true,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
@ -1943,12 +1955,22 @@ pub const Value = extern union {
|
|||||||
);
|
);
|
||||||
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||||
result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
|
result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(arena, result_bigint.toConst());
|
||||||
|
}
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
fn fromBigInt(arena: *Allocator, big_int: BigIntConst) !Value {
|
||||||
return Value.Tag.int_big_positive.create(arena, result_limbs);
|
if (big_int.positive) {
|
||||||
|
if (big_int.to(u64)) |x| {
|
||||||
|
return Value.Tag.int_u64.create(arena, x);
|
||||||
|
} else |_| {
|
||||||
|
return Value.Tag.int_big_positive.create(arena, big_int.limbs);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Value.Tag.int_big_negative.create(arena, result_limbs);
|
if (big_int.to(i64)) |x| {
|
||||||
|
return Value.Tag.int_i64.create(arena, x);
|
||||||
|
} else |_| {
|
||||||
|
return Value.Tag.int_big_negative.create(arena, big_int.limbs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1975,13 +1997,7 @@ pub const Value = extern union {
|
|||||||
);
|
);
|
||||||
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||||
result_bigint.addSat(lhs_bigint, rhs_bigint, info.signedness, info.bits);
|
result_bigint.addSat(lhs_bigint, rhs_bigint, info.signedness, info.bits);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(arena, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(arena, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(arena, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Supports both floats and ints; handles undefined.
|
/// Supports both floats and ints; handles undefined.
|
||||||
@ -2010,13 +2026,7 @@ pub const Value = extern union {
|
|||||||
);
|
);
|
||||||
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||||
result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
|
result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(arena, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(arena, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(arena, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Supports integers only; asserts neither operand is undefined.
|
/// Supports integers only; asserts neither operand is undefined.
|
||||||
@ -2042,13 +2052,7 @@ pub const Value = extern union {
|
|||||||
);
|
);
|
||||||
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||||
result_bigint.subSat(lhs_bigint, rhs_bigint, info.signedness, info.bits);
|
result_bigint.subSat(lhs_bigint, rhs_bigint, info.signedness, info.bits);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(arena, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(arena, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(arena, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Supports both floats and ints; handles undefined.
|
/// Supports both floats and ints; handles undefined.
|
||||||
@ -2082,13 +2086,7 @@ pub const Value = extern union {
|
|||||||
);
|
);
|
||||||
defer arena.free(limbs_buffer);
|
defer arena.free(limbs_buffer);
|
||||||
result_bigint.mulWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits, limbs_buffer, arena);
|
result_bigint.mulWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits, limbs_buffer, arena);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(arena, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(arena, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(arena, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Supports integers only; asserts neither operand is undefined.
|
/// Supports integers only; asserts neither operand is undefined.
|
||||||
@ -2124,13 +2122,7 @@ pub const Value = extern union {
|
|||||||
defer arena.free(limbs_buffer);
|
defer arena.free(limbs_buffer);
|
||||||
result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, arena);
|
result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, arena);
|
||||||
result_bigint.saturate(result_bigint.toConst(), info.signedness, info.bits);
|
result_bigint.saturate(result_bigint.toConst(), info.signedness, info.bits);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(arena, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(arena, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(arena, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Supports both floats and ints; handles undefined.
|
/// Supports both floats and ints; handles undefined.
|
||||||
@ -2174,13 +2166,7 @@ pub const Value = extern union {
|
|||||||
|
|
||||||
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||||
result_bigint.bitNotWrap(val_bigint, info.signedness, info.bits);
|
result_bigint.bitNotWrap(val_bigint, info.signedness, info.bits);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(arena, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(arena, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(arena, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// operands must be integers; handles undefined.
|
/// operands must be integers; handles undefined.
|
||||||
@ -2200,13 +2186,7 @@ pub const Value = extern union {
|
|||||||
);
|
);
|
||||||
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||||
result_bigint.bitAnd(lhs_bigint, rhs_bigint);
|
result_bigint.bitAnd(lhs_bigint, rhs_bigint);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(arena, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(arena, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(arena, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// operands must be integers; handles undefined.
|
/// operands must be integers; handles undefined.
|
||||||
@ -2239,13 +2219,7 @@ pub const Value = extern union {
|
|||||||
);
|
);
|
||||||
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||||
result_bigint.bitOr(lhs_bigint, rhs_bigint);
|
result_bigint.bitOr(lhs_bigint, rhs_bigint);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(arena, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(arena, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(arena, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// operands must be integers; handles undefined.
|
/// operands must be integers; handles undefined.
|
||||||
@ -2265,13 +2239,7 @@ pub const Value = extern union {
|
|||||||
);
|
);
|
||||||
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||||
result_bigint.bitXor(lhs_bigint, rhs_bigint);
|
result_bigint.bitXor(lhs_bigint, rhs_bigint);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(arena, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(arena, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(arena, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intAdd(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
pub fn intAdd(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
||||||
@ -2287,13 +2255,7 @@ pub const Value = extern union {
|
|||||||
);
|
);
|
||||||
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||||
result_bigint.add(lhs_bigint, rhs_bigint);
|
result_bigint.add(lhs_bigint, rhs_bigint);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(allocator, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(allocator, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(allocator, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intSub(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
pub fn intSub(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
||||||
@ -2309,13 +2271,7 @@ pub const Value = extern union {
|
|||||||
);
|
);
|
||||||
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||||
result_bigint.sub(lhs_bigint, rhs_bigint);
|
result_bigint.sub(lhs_bigint, rhs_bigint);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(allocator, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(allocator, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(allocator, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intDiv(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
pub fn intDiv(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
||||||
@ -2340,13 +2296,7 @@ pub const Value = extern union {
|
|||||||
var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
|
var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
|
||||||
var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
|
var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
|
||||||
result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
|
result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
|
||||||
const result_limbs = result_q.limbs[0..result_q.len];
|
return fromBigInt(allocator, result_q.toConst());
|
||||||
|
|
||||||
if (result_q.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(allocator, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(allocator, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intDivFloor(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
pub fn intDivFloor(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
||||||
@ -2371,13 +2321,7 @@ pub const Value = extern union {
|
|||||||
var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
|
var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
|
||||||
var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
|
var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
|
||||||
result_q.divFloor(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
|
result_q.divFloor(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
|
||||||
const result_limbs = result_q.limbs[0..result_q.len];
|
return fromBigInt(allocator, result_q.toConst());
|
||||||
|
|
||||||
if (result_q.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(allocator, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(allocator, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intRem(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
pub fn intRem(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
||||||
@ -2404,13 +2348,7 @@ pub const Value = extern union {
|
|||||||
var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
|
var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
|
||||||
var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
|
var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
|
||||||
result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
|
result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
|
||||||
const result_limbs = result_r.limbs[0..result_r.len];
|
return fromBigInt(allocator, result_r.toConst());
|
||||||
|
|
||||||
if (result_r.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(allocator, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(allocator, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intMod(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
pub fn intMod(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
||||||
@ -2435,13 +2373,7 @@ pub const Value = extern union {
|
|||||||
var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
|
var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
|
||||||
var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
|
var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
|
||||||
result_q.divFloor(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
|
result_q.divFloor(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
|
||||||
const result_limbs = result_r.limbs[0..result_r.len];
|
return fromBigInt(allocator, result_r.toConst());
|
||||||
|
|
||||||
if (result_r.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(allocator, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(allocator, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the value is a floating point type and is NaN. Returns false otherwise.
|
/// Returns true if the value is a floating point type and is NaN. Returns false otherwise.
|
||||||
@ -2487,13 +2419,7 @@ pub const Value = extern union {
|
|||||||
);
|
);
|
||||||
defer allocator.free(limbs_buffer);
|
defer allocator.free(limbs_buffer);
|
||||||
result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, allocator);
|
result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, allocator);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(allocator, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(allocator, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(allocator, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intTrunc(val: Value, allocator: *Allocator, signedness: std.builtin.Signedness, bits: u16) !Value {
|
pub fn intTrunc(val: Value, allocator: *Allocator, signedness: std.builtin.Signedness, bits: u16) !Value {
|
||||||
@ -2507,13 +2433,7 @@ pub const Value = extern union {
|
|||||||
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||||
|
|
||||||
result_bigint.truncate(val_bigint, signedness, bits);
|
result_bigint.truncate(val_bigint, signedness, bits);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(allocator, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(allocator, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(allocator, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shl(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
pub fn shl(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
||||||
@ -2532,13 +2452,7 @@ pub const Value = extern union {
|
|||||||
.len = undefined,
|
.len = undefined,
|
||||||
};
|
};
|
||||||
result_bigint.shiftLeft(lhs_bigint, shift);
|
result_bigint.shiftLeft(lhs_bigint, shift);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(allocator, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(allocator, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(allocator, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shlSat(
|
pub fn shlSat(
|
||||||
@ -2565,13 +2479,7 @@ pub const Value = extern union {
|
|||||||
.len = undefined,
|
.len = undefined,
|
||||||
};
|
};
|
||||||
result_bigint.shiftLeftSat(lhs_bigint, shift, info.signedness, info.bits);
|
result_bigint.shiftLeftSat(lhs_bigint, shift, info.signedness, info.bits);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(arena, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(arena, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(arena, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shr(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
pub fn shr(lhs: Value, rhs: Value, allocator: *Allocator) !Value {
|
||||||
@ -2590,13 +2498,7 @@ pub const Value = extern union {
|
|||||||
.len = undefined,
|
.len = undefined,
|
||||||
};
|
};
|
||||||
result_bigint.shiftRight(lhs_bigint, shift);
|
result_bigint.shiftRight(lhs_bigint, shift);
|
||||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
return fromBigInt(allocator, result_bigint.toConst());
|
||||||
|
|
||||||
if (result_bigint.positive) {
|
|
||||||
return Value.Tag.int_big_positive.create(allocator, result_limbs);
|
|
||||||
} else {
|
|
||||||
return Value.Tag.int_big_negative.create(allocator, result_limbs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn floatAdd(
|
pub fn floatAdd(
|
||||||
|
|||||||
@ -50,6 +50,7 @@ test {
|
|||||||
_ = @import("behavior/null.zig");
|
_ = @import("behavior/null.zig");
|
||||||
_ = @import("behavior/optional.zig");
|
_ = @import("behavior/optional.zig");
|
||||||
_ = @import("behavior/pointers.zig");
|
_ = @import("behavior/pointers.zig");
|
||||||
|
_ = @import("behavior/popcount.zig");
|
||||||
_ = @import("behavior/ptrcast.zig");
|
_ = @import("behavior/ptrcast.zig");
|
||||||
_ = @import("behavior/pub_enum.zig");
|
_ = @import("behavior/pub_enum.zig");
|
||||||
_ = @import("behavior/saturating_arithmetic.zig");
|
_ = @import("behavior/saturating_arithmetic.zig");
|
||||||
@ -153,7 +154,7 @@ test {
|
|||||||
_ = @import("behavior/null_stage1.zig");
|
_ = @import("behavior/null_stage1.zig");
|
||||||
_ = @import("behavior/optional_stage1.zig");
|
_ = @import("behavior/optional_stage1.zig");
|
||||||
_ = @import("behavior/pointers_stage1.zig");
|
_ = @import("behavior/pointers_stage1.zig");
|
||||||
_ = @import("behavior/popcount.zig");
|
_ = @import("behavior/popcount_stage1.zig");
|
||||||
_ = @import("behavior/ptrcast_stage1.zig");
|
_ = @import("behavior/ptrcast_stage1.zig");
|
||||||
_ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
|
_ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
|
||||||
_ = @import("behavior/reflection.zig");
|
_ = @import("behavior/reflection.zig");
|
||||||
|
|||||||
@ -44,19 +44,3 @@ fn testPopCountIntegers() !void {
|
|||||||
try expect(@popCount(i128, 0b11111111000110001100010000100001000011000011100101010001) == 24);
|
try expect(@popCount(i128, 0b11111111000110001100010000100001000011000011100101010001) == 24);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "@popCount vectors" {
|
|
||||||
comptime try testPopCountVectors();
|
|
||||||
try testPopCountVectors();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn testPopCountVectors() !void {
|
|
||||||
{
|
|
||||||
var x: Vector(8, u32) = [1]u32{0xffffffff} ** 8;
|
|
||||||
try expectEqual([1]u6{32} ** 8, @as([8]u6, @popCount(u32, x)));
|
|
||||||
}
|
|
||||||
{
|
|
||||||
var x: Vector(8, i16) = [1]i16{-1} ** 8;
|
|
||||||
try expectEqual([1]u5{16} ** 8, @as([8]u5, @popCount(i16, x)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
24
test/behavior/popcount_stage1.zig
Normal file
24
test/behavior/popcount_stage1.zig
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const expect = std.testing.expect;
|
||||||
|
const expectEqual = std.testing.expectEqual;
|
||||||
|
const Vector = std.meta.Vector;
|
||||||
|
|
||||||
|
test "@popCount vectors" {
|
||||||
|
comptime try testPopCountVectors();
|
||||||
|
try testPopCountVectors();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn testPopCountVectors() !void {
|
||||||
|
{
|
||||||
|
var x: Vector(8, u32) = [1]u32{0xffffffff} ** 8;
|
||||||
|
const expected = [1]u6{32} ** 8;
|
||||||
|
const result: [8]u6 = @popCount(u32, x);
|
||||||
|
try expect(std.mem.eql(u6, &expected, &result));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var x: Vector(8, i16) = [1]i16{-1} ** 8;
|
||||||
|
const expected = [1]u5{16} ** 8;
|
||||||
|
const result: [8]u5 = @popCount(i16, x);
|
||||||
|
try expect(std.mem.eql(u5, &expected, &result));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user