╭ mulc3.zig ────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
.. aarch64_outline_atomics.zig absv.zig absvdi2.zig absvdi2_test.zig absvsi2.zig absvsi2_test.zig absvti2.zig absvti2_test.zig addf3.zig addf3_test.zig addvdi3.zig addvsi3.zig arm.zig atomics.zig aulldiv.zig aullrem.zig bitreverse.zig bitreversedi2_test.zig bitreversesi2_test.zig bitreverseti2_test.zig bswap.zig bswapdi2_test.zig bswapsi2_test.zig bswapti2_test.zig clear_cache.zig clzdi2_test.zig clzsi2_test.zig clzti2_test.zig cmp.zig cmpdi2_test.zig cmpsi2_test.zig cmpti2_test.zig comparedf2_test.zig comparef.zig comparesf2_test.zig cos.zig count0bits.zig ctzdi2_test.zig ctzsi2_test.zig ctzti2_test.zig divc3.zig divc3_test.zig divdf3.zig divdf3_test.zig divmodei4.zig divsf3.zig divsf3_test.zig divtf3.zig divtf3_test.zig divti3_test.zig divxf3.zig divxf3_test.zig emutls.zig exp.zig exp2.zig exp_f128.zig extendf.zig extendf_test.zig fabs.zig ffsdi2_test.zig ffssi2_test.zig ffsti2_test.zig float_from_int.zig float_from_int_test.zig floor_ceil.zig fma.zig fmax.zig fmin.zig fmod.zig fmodq_test.zig fmodx_test.zig hexagon.zig int.zig int_from_float.zig int_from_float_test.zig limb64.zig log.zig log10.zig log2.zig log_f128.zig memcpy.zig memmove.zig modti3_test.zig mulXi3.zig mulXi3_test.zig ╭─────────────────────────────────╮ │mulc3.zig │ ╰─────────────────────────────────╯ mulc3_test.zig mulf3.zig mulf3_test.zig mulo.zig mulodi4_test.zig mulosi4_test.zig muloti4_test.zig mulvsi3.zig negdi2_test.zig negsi2_test.zig negti2_test.zig negv.zig negvdi2_test.zig negvsi2_test.zig negvti2_test.zig os_version_check.zig parity.zig paritydi2_test.zig paritysi2_test.zig parityti2_test.zig popcount.zig popcountdi2_test.zig popcountsi2_test.zig popcountti2_test.zig powiXf2.zig powiXf2_test.zig rem_pio2.zig rem_pio2_large.zig rem_pio2f.zig rem_pio2l.zig round.zig shift.zig shift_test.zig sin.zig sincos.zig sqrt.zig ssp.zig stack_probe.zig subvdi3.zig subvsi3.zig tan.zig trig.zig trunc.zig truncf.zig truncf_test.zig ucmpdi2_test.zig ucmpsi2_test.zig ucmpti2_test.zig udivmod.zig udivmoddi4_test.zig udivmodei4.zig udivmodsi4_test.zig udivmodti4_test.zig
1 const std = @import("std"); 2 const isNan = std.math.isNan; 3 const isInf = std.math.isInf; 4 const copysign = std.math.copysign; 5 6 const compiler_rt = @import("../compiler_rt.zig"); 7 const symbol = compiler_rt.symbol; 8 const Complex = compiler_rt.Complex; 9 10 comptime { 11 if (@import("builtin").zig_backend != .stage2_c) { 12 symbol(&__mulhc3, "__mulhc3"); 13 symbol(&__mulsc3, "__mulsc3"); 14 symbol(&__muldc3, "__muldc3"); 15 symbol(&__mulxc3, "__mulxc3"); 16 if (compiler_rt.want_ppc_abi) { 17 symbol(&__multc3, "__mulkc3"); 18 } else { 19 symbol(&__multc3, "__multc3"); 20 } 21 } 22 } 23 24 fn __mulhc3(lhs_real: compiler_rt.f16.Abi, lhs_imag: compiler_rt.f16.Abi, rhs_real: compiler_rt.f16.Abi, rhs_imag: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.complex.Abi { 25 return compiler_rt.f16.complex.toAbi(mul_cf16( 26 compiler_rt.f16.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), 27 compiler_rt.f16.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), 28 )); 29 } 30 pub fn mul_cf16(a: Complex(f16), b: Complex(f16)) Complex(f16) { 31 return mulc3(f16, a, b); 32 } 33 34 fn __mulsc3(lhs_real: compiler_rt.f32.Abi, lhs_imag: compiler_rt.f32.Abi, rhs_real: compiler_rt.f32.Abi, rhs_imag: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.complex.Abi { 35 return compiler_rt.f32.complex.toAbi(mul_cf32( 36 compiler_rt.f32.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), 37 compiler_rt.f32.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), 38 )); 39 } 40 pub fn mul_cf32(a: Complex(f32), b: Complex(f32)) Complex(f32) { 41 return mulc3(f32, a, b); 42 } 43 44 fn __muldc3(lhs_real: compiler_rt.f64.Abi, lhs_imag: compiler_rt.f64.Abi, rhs_real: compiler_rt.f64.Abi, rhs_imag: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.complex.Abi { 45 return compiler_rt.f64.complex.toAbi(mul_cf64( 46 compiler_rt.f64.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), 47 compiler_rt.f64.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), 48 )); 49 } 50 pub fn mul_cf64(a: Complex(f64), b: Complex(f64)) Complex(f64) { 51 return mulc3(f64, a, b); 52 } 53 54 fn __mulxc3(lhs_real: compiler_rt.f80.Abi, lhs_imag: compiler_rt.f80.Abi, rhs_real: compiler_rt.f80.Abi, rhs_imag: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.complex.Abi { 55 return compiler_rt.f80.complex.toAbi(mul_cf80( 56 compiler_rt.f80.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), 57 compiler_rt.f80.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), 58 )); 59 } 60 pub fn mul_cf80(a: Complex(f80), b: Complex(f80)) Complex(f80) { 61 return mulc3(f80, a, b); 62 } 63 64 fn __multc3(lhs_real: compiler_rt.f128.Abi, lhs_imag: compiler_rt.f128.Abi, rhs_real: compiler_rt.f128.Abi, rhs_imag: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.complex.Abi { 65 return compiler_rt.f128.complex.toAbi(mul_cf128( 66 compiler_rt.f128.complex.fromAbi(.{ .real = lhs_real, .imag = lhs_imag }), 67 compiler_rt.f128.complex.fromAbi(.{ .real = rhs_real, .imag = rhs_imag }), 68 )); 69 } 70 pub fn mul_cf128(a: Complex(f128), b: Complex(f128)) Complex(f128) { 71 return mulc3(f128, a, b); 72 } 73 74 /// Implementation based on Annex G of C17 Standard (N2176) 75 inline fn mulc3(comptime T: type, lhs: Complex(T), rhs: Complex(T)) Complex(T) { 76 var a = lhs.real; 77 var b = lhs.imag; 78 var c = rhs.real; 79 var d = rhs.imag; 80 81 const ac = a * c; 82 const bd = b * d; 83 const ad = a * d; 84 const bc = b * c; 85 86 const zero: T = 0.0; 87 const one: T = 1.0; 88 89 const z: Complex(T) = .{ 90 .real = ac - bd, 91 .imag = ad + bc, 92 }; 93 if (isNan(z.real) and isNan(z.imag)) { 94 var recalc: bool = false; 95 96 if (isInf(a) or isInf(b)) { // (a + ib) is infinite 97 98 // "Box" the infinity (+/-inf goes to +/-1, all finite values go to 0) 99 a = copysign(if (isInf(a)) one else zero, a); 100 b = copysign(if (isInf(b)) one else zero, b); 101 102 // Replace NaNs in the other factor with (signed) 0 103 if (isNan(c)) c = copysign(zero, c); 104 if (isNan(d)) d = copysign(zero, d); 105 106 recalc = true; 107 } 108 109 if (isInf(c) or isInf(d)) { // (c + id) is infinite 110 111 // "Box" the infinity (+/-inf goes to +/-1, all finite values go to 0) 112 c = copysign(if (isInf(c)) one else zero, c); 113 d = copysign(if (isInf(d)) one else zero, d); 114 115 // Replace NaNs in the other factor with (signed) 0 116 if (isNan(a)) a = copysign(zero, a); 117 if (isNan(b)) b = copysign(zero, b); 118 119 recalc = true; 120 } 121 122 if (!recalc and (isInf(ac) or isInf(bd) or isInf(ad) or isInf(bc))) { 123 124 // Recover infinities from overflow by changing NaNs to 0 125 if (isNan(a)) a = copysign(zero, a); 126 if (isNan(b)) b = copysign(zero, b); 127 if (isNan(c)) c = copysign(zero, c); 128 if (isNan(d)) d = copysign(zero, d); 129 130 recalc = true; 131 } 132 if (recalc) { 133 return .{ 134 .real = std.math.inf(T) * (a * c - b * d), 135 .imag = std.math.inf(T) * (a * d + b * c), 136 }; 137 } 138 } 139 return z; 140 } 141 142 test { 143 _ = @import("mulc3_test.zig"); 144 } 145