1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#![cfg(target_feature = "pclmulqdq")]

use super::*;

/// Performs a "carryless" multiplication of two `i64` values.
///
/// You specify `m128i` expressions and then `, lane 0` or `, lane 1` for each
/// one to select which of the two `i64` lanes is used in the multiplication.
///
/// ```
/// # use safe_arch::*;
/// let x = m128i::from([2_i64, 3]);
/// let y = m128i::from([4_i64, 500]);
/// //
/// let c: [i64; 2] = mul_i64_carryless_m128i!(x, lane 0, y, lane 0).into();
/// assert_eq!(c, [8_i64, 0]);
/// let c: [i64; 2] = mul_i64_carryless_m128i!(x, lane 1, y, lane 0).into();
/// assert_eq!(c, [12_i64, 0]);
/// let c: [i64; 2] = mul_i64_carryless_m128i!(x, lane 0, y, lane 1).into();
/// assert_eq!(c, [1000_i64, 0]);
/// let c: [i64; 2] = mul_i64_carryless_m128i!(x, lane 1, y, lane 1).into();
/// assert_eq!(c, [540_i64, 0]); // not 1500 like a normal mul would be!
/// ```
#[macro_export]
#[cfg_attr(docs_rs, doc(cfg(target_feature = "pclmulqdq")))]
macro_rules! mul_i64_carryless_m128i {
  ($a:expr, lane 0, $b:expr, lane 0) => {{
    let a: $crate::m128i = $a;
    let b: $crate::m128i = $b;
    #[cfg(target_arch = "x86")]
    use ::core::arch::x86::_mm_clmulepi64_si128;
    #[cfg(target_arch = "x86_64")]
    use ::core::arch::x86_64::_mm_clmulepi64_si128;
    $crate::m128i(unsafe { _mm_clmulepi64_si128(a.0, b.0, 0_i32) })
  }};
  ($a:expr, lane 1, $b:expr, lane 0) => {{
    let a: $crate::m128i = $a;
    let b: $crate::m128i = $b;
    #[cfg(target_arch = "x86")]
    use ::core::arch::x86::_mm_clmulepi64_si128;
    #[cfg(target_arch = "x86_64")]
    use ::core::arch::x86_64::_mm_clmulepi64_si128;
    $crate::m128i(unsafe { _mm_clmulepi64_si128(a.0, b.0, 0b1_i32) })
  }};
  ($a:expr, lane 0, $b:expr, lane 1) => {{
    let a: $crate::m128i = $a;
    let b: $crate::m128i = $b;
    #[cfg(target_arch = "x86")]
    use ::core::arch::x86::_mm_clmulepi64_si128;
    #[cfg(target_arch = "x86_64")]
    use ::core::arch::x86_64::_mm_clmulepi64_si128;
    $crate::m128i(unsafe { _mm_clmulepi64_si128(a.0, b.0, 0b1_0000_i32) })
  }};
  ($a:expr, lane 1, $b:expr, lane 1) => {{
    let a: $crate::m128i = $a;
    let b: $crate::m128i = $b;
    #[cfg(target_arch = "x86")]
    use ::core::arch::x86::_mm_clmulepi64_si128;
    #[cfg(target_arch = "x86_64")]
    use ::core::arch::x86_64::_mm_clmulepi64_si128;
    $crate::m128i(unsafe { _mm_clmulepi64_si128(a.0, b.0, 0b1_0001_i32) })
  }};
}