1 use super::*; 2 3 pick! { 4 if #[cfg(target_feature="sse2")] { 5 #[derive(Default, Clone, Copy, PartialEq, Eq)] 6 #[repr(C, align(16))] 7 pub struct i8x16 { sse: m128i } 8 } else if #[cfg(target_feature="simd128")] { 9 use core::arch::wasm32::*; 10 11 #[derive(Clone, Copy)] 12 #[repr(transparent)] 13 pub struct i8x16 { simd: v128 } 14 15 impl Default for i8x16 { 16 fn default() -> Self { 17 Self::splat(0) 18 } 19 } 20 21 impl PartialEq for i8x16 { 22 fn eq(&self, other: &Self) -> bool { 23 u8x16_all_true(i8x16_eq(self.simd, other.simd)) 24 } 25 } 26 27 impl Eq for i8x16 { } 28 } else { 29 #[derive(Default, Clone, Copy, PartialEq, Eq)] 30 #[repr(C, align(16))] 31 pub struct i8x16 { arr: [i8;16] } 32 } 33 } 34 35 int_uint_consts!(i8, 16, i8x16, i8x16, i8a16, const_i8_as_i8x16, 128); 36 37 unsafe impl Zeroable for i8x16 {} 38 unsafe impl Pod for i8x16 {} 39 40 impl Add for i8x16 { 41 type Output = Self; 42 #[inline] 43 #[must_use] add(self, rhs: Self) -> Self::Output44 fn add(self, rhs: Self) -> Self::Output { 45 pick! { 46 if #[cfg(target_feature="sse2")] { 47 Self { sse: add_i8_m128i(self.sse, rhs.sse) } 48 } else if #[cfg(target_feature="simd128")] { 49 Self { simd: i8x16_add(self.simd, rhs.simd) } 50 } else { 51 Self { arr: [ 52 self.arr[0].wrapping_add(rhs.arr[0]), 53 self.arr[1].wrapping_add(rhs.arr[1]), 54 self.arr[2].wrapping_add(rhs.arr[2]), 55 self.arr[3].wrapping_add(rhs.arr[3]), 56 self.arr[4].wrapping_add(rhs.arr[4]), 57 self.arr[5].wrapping_add(rhs.arr[5]), 58 self.arr[6].wrapping_add(rhs.arr[6]), 59 self.arr[7].wrapping_add(rhs.arr[7]), 60 self.arr[8].wrapping_add(rhs.arr[8]), 61 self.arr[9].wrapping_add(rhs.arr[9]), 62 self.arr[10].wrapping_add(rhs.arr[10]), 63 self.arr[11].wrapping_add(rhs.arr[11]), 64 self.arr[12].wrapping_add(rhs.arr[12]), 65 self.arr[13].wrapping_add(rhs.arr[13]), 66 self.arr[14].wrapping_add(rhs.arr[14]), 67 self.arr[15].wrapping_add(rhs.arr[15]), 68 ]} 69 } 70 } 71 } 72 } 73 74 impl Sub for i8x16 { 75 type Output = Self; 76 #[inline] 77 #[must_use] sub(self, rhs: Self) -> Self::Output78 fn sub(self, rhs: Self) -> Self::Output { 79 pick! { 80 if #[cfg(target_feature="sse2")] { 81 Self { sse: sub_i8_m128i(self.sse, rhs.sse) } 82 } else if #[cfg(target_feature="simd128")] { 83 Self { simd: i8x16_sub(self.simd, rhs.simd) } 84 } else { 85 Self { arr: [ 86 self.arr[0].wrapping_sub(rhs.arr[0]), 87 self.arr[1].wrapping_sub(rhs.arr[1]), 88 self.arr[2].wrapping_sub(rhs.arr[2]), 89 self.arr[3].wrapping_sub(rhs.arr[3]), 90 self.arr[4].wrapping_sub(rhs.arr[4]), 91 self.arr[5].wrapping_sub(rhs.arr[5]), 92 self.arr[6].wrapping_sub(rhs.arr[6]), 93 self.arr[7].wrapping_sub(rhs.arr[7]), 94 self.arr[8].wrapping_sub(rhs.arr[8]), 95 self.arr[9].wrapping_sub(rhs.arr[9]), 96 self.arr[10].wrapping_sub(rhs.arr[10]), 97 self.arr[11].wrapping_sub(rhs.arr[11]), 98 self.arr[12].wrapping_sub(rhs.arr[12]), 99 self.arr[13].wrapping_sub(rhs.arr[13]), 100 self.arr[14].wrapping_sub(rhs.arr[14]), 101 self.arr[15].wrapping_sub(rhs.arr[15]), 102 ]} 103 } 104 } 105 } 106 } 107 108 impl Add<i8> for i8x16 { 109 type Output = Self; 110 #[inline] 111 #[must_use] add(self, rhs: i8) -> Self::Output112 fn add(self, rhs: i8) -> Self::Output { 113 self.add(Self::splat(rhs)) 114 } 115 } 116 117 impl Sub<i8> for i8x16 { 118 type Output = Self; 119 #[inline] 120 #[must_use] sub(self, rhs: i8) -> Self::Output121 fn sub(self, rhs: i8) -> Self::Output { 122 self.sub(Self::splat(rhs)) 123 } 124 } 125 126 impl Add<i8x16> for i8 { 127 type Output = i8x16; 128 #[inline] 129 #[must_use] add(self, rhs: i8x16) -> Self::Output130 fn add(self, rhs: i8x16) -> Self::Output { 131 i8x16::splat(self).add(rhs) 132 } 133 } 134 135 impl Sub<i8x16> for i8 { 136 type Output = i8x16; 137 #[inline] 138 #[must_use] sub(self, rhs: i8x16) -> Self::Output139 fn sub(self, rhs: i8x16) -> Self::Output { 140 i8x16::splat(self).sub(rhs) 141 } 142 } 143 144 impl BitAnd for i8x16 { 145 type Output = Self; 146 #[inline] 147 #[must_use] bitand(self, rhs: Self) -> Self::Output148 fn bitand(self, rhs: Self) -> Self::Output { 149 pick! { 150 if #[cfg(target_feature="sse2")] { 151 Self { sse: bitand_m128i(self.sse, rhs.sse) } 152 } else if #[cfg(target_feature="simd128")] { 153 Self { simd: v128_and(self.simd, rhs.simd) } 154 } else { 155 Self { arr: [ 156 self.arr[0].bitand(rhs.arr[0]), 157 self.arr[1].bitand(rhs.arr[1]), 158 self.arr[2].bitand(rhs.arr[2]), 159 self.arr[3].bitand(rhs.arr[3]), 160 self.arr[4].bitand(rhs.arr[4]), 161 self.arr[5].bitand(rhs.arr[5]), 162 self.arr[6].bitand(rhs.arr[6]), 163 self.arr[7].bitand(rhs.arr[7]), 164 self.arr[8].bitand(rhs.arr[8]), 165 self.arr[9].bitand(rhs.arr[9]), 166 self.arr[10].bitand(rhs.arr[10]), 167 self.arr[11].bitand(rhs.arr[11]), 168 self.arr[12].bitand(rhs.arr[12]), 169 self.arr[13].bitand(rhs.arr[13]), 170 self.arr[14].bitand(rhs.arr[14]), 171 self.arr[15].bitand(rhs.arr[15]), 172 ]} 173 } 174 } 175 } 176 } 177 178 impl BitOr for i8x16 { 179 type Output = Self; 180 #[inline] 181 #[must_use] bitor(self, rhs: Self) -> Self::Output182 fn bitor(self, rhs: Self) -> Self::Output { 183 pick! { 184 if #[cfg(target_feature="sse2")] { 185 Self { sse: bitor_m128i(self.sse, rhs.sse) } 186 } else if #[cfg(target_feature="simd128")] { 187 Self { simd: v128_or(self.simd, rhs.simd) } 188 } else { 189 Self { arr: [ 190 self.arr[0].bitor(rhs.arr[0]), 191 self.arr[1].bitor(rhs.arr[1]), 192 self.arr[2].bitor(rhs.arr[2]), 193 self.arr[3].bitor(rhs.arr[3]), 194 self.arr[4].bitor(rhs.arr[4]), 195 self.arr[5].bitor(rhs.arr[5]), 196 self.arr[6].bitor(rhs.arr[6]), 197 self.arr[7].bitor(rhs.arr[7]), 198 self.arr[8].bitor(rhs.arr[8]), 199 self.arr[9].bitor(rhs.arr[9]), 200 self.arr[10].bitor(rhs.arr[10]), 201 self.arr[11].bitor(rhs.arr[11]), 202 self.arr[12].bitor(rhs.arr[12]), 203 self.arr[13].bitor(rhs.arr[13]), 204 self.arr[14].bitor(rhs.arr[14]), 205 self.arr[15].bitor(rhs.arr[15]), 206 ]} 207 } 208 } 209 } 210 } 211 212 impl BitXor for i8x16 { 213 type Output = Self; 214 #[inline] 215 #[must_use] bitxor(self, rhs: Self) -> Self::Output216 fn bitxor(self, rhs: Self) -> Self::Output { 217 pick! { 218 if #[cfg(target_feature="sse2")] { 219 Self { sse: bitxor_m128i(self.sse, rhs.sse) } 220 } else if #[cfg(target_feature="simd128")] { 221 Self { simd: v128_xor(self.simd, rhs.simd) } 222 } else { 223 Self { arr: [ 224 self.arr[0].bitxor(rhs.arr[0]), 225 self.arr[1].bitxor(rhs.arr[1]), 226 self.arr[2].bitxor(rhs.arr[2]), 227 self.arr[3].bitxor(rhs.arr[3]), 228 self.arr[4].bitxor(rhs.arr[4]), 229 self.arr[5].bitxor(rhs.arr[5]), 230 self.arr[6].bitxor(rhs.arr[6]), 231 self.arr[7].bitxor(rhs.arr[7]), 232 self.arr[8].bitxor(rhs.arr[8]), 233 self.arr[9].bitxor(rhs.arr[9]), 234 self.arr[10].bitxor(rhs.arr[10]), 235 self.arr[11].bitxor(rhs.arr[11]), 236 self.arr[12].bitxor(rhs.arr[12]), 237 self.arr[13].bitxor(rhs.arr[13]), 238 self.arr[14].bitxor(rhs.arr[14]), 239 self.arr[15].bitxor(rhs.arr[15]), 240 ]} 241 } 242 } 243 } 244 } 245 246 impl CmpEq for i8x16 { 247 type Output = Self; 248 #[inline] 249 #[must_use] cmp_eq(self, rhs: Self) -> Self::Output250 fn cmp_eq(self, rhs: Self) -> Self::Output { 251 pick! { 252 if #[cfg(target_feature="sse2")] { 253 Self { sse: cmp_eq_mask_i8_m128i(self.sse, rhs.sse) } 254 } else if #[cfg(target_feature="simd128")] { 255 Self { simd: i8x16_eq(self.simd, rhs.simd) } 256 } else { 257 Self { arr: [ 258 if self.arr[0] == rhs.arr[0] { -1 } else { 0 }, 259 if self.arr[1] == rhs.arr[1] { -1 } else { 0 }, 260 if self.arr[2] == rhs.arr[2] { -1 } else { 0 }, 261 if self.arr[3] == rhs.arr[3] { -1 } else { 0 }, 262 if self.arr[4] == rhs.arr[4] { -1 } else { 0 }, 263 if self.arr[5] == rhs.arr[5] { -1 } else { 0 }, 264 if self.arr[6] == rhs.arr[6] { -1 } else { 0 }, 265 if self.arr[7] == rhs.arr[7] { -1 } else { 0 }, 266 if self.arr[8] == rhs.arr[8] { -1 } else { 0 }, 267 if self.arr[9] == rhs.arr[9] { -1 } else { 0 }, 268 if self.arr[10] == rhs.arr[10] { -1 } else { 0 }, 269 if self.arr[11] == rhs.arr[11] { -1 } else { 0 }, 270 if self.arr[12] == rhs.arr[12] { -1 } else { 0 }, 271 if self.arr[13] == rhs.arr[13] { -1 } else { 0 }, 272 if self.arr[14] == rhs.arr[14] { -1 } else { 0 }, 273 if self.arr[15] == rhs.arr[15] { -1 } else { 0 }, 274 ]} 275 } 276 } 277 } 278 } 279 280 impl CmpGt for i8x16 { 281 type Output = Self; 282 #[inline] 283 #[must_use] cmp_gt(self, rhs: Self) -> Self::Output284 fn cmp_gt(self, rhs: Self) -> Self::Output { 285 pick! { 286 if #[cfg(target_feature="sse2")] { 287 Self { sse: cmp_gt_mask_i8_m128i(self.sse, rhs.sse) } 288 } else if #[cfg(target_feature="simd128")] { 289 Self { simd: i8x16_gt(self.simd, rhs.simd) } 290 } else { 291 Self { arr: [ 292 if self.arr[0] > rhs.arr[0] { -1 } else { 0 }, 293 if self.arr[1] > rhs.arr[1] { -1 } else { 0 }, 294 if self.arr[2] > rhs.arr[2] { -1 } else { 0 }, 295 if self.arr[3] > rhs.arr[3] { -1 } else { 0 }, 296 if self.arr[4] > rhs.arr[4] { -1 } else { 0 }, 297 if self.arr[5] > rhs.arr[5] { -1 } else { 0 }, 298 if self.arr[6] > rhs.arr[6] { -1 } else { 0 }, 299 if self.arr[7] > rhs.arr[7] { -1 } else { 0 }, 300 if self.arr[8] > rhs.arr[8] { -1 } else { 0 }, 301 if self.arr[9] > rhs.arr[9] { -1 } else { 0 }, 302 if self.arr[10] > rhs.arr[10] { -1 } else { 0 }, 303 if self.arr[11] > rhs.arr[11] { -1 } else { 0 }, 304 if self.arr[12] > rhs.arr[12] { -1 } else { 0 }, 305 if self.arr[13] > rhs.arr[13] { -1 } else { 0 }, 306 if self.arr[14] > rhs.arr[14] { -1 } else { 0 }, 307 if self.arr[15] > rhs.arr[15] { -1 } else { 0 }, 308 ]} 309 } 310 } 311 } 312 } 313 314 impl CmpLt for i8x16 { 315 type Output = Self; 316 #[inline] 317 #[must_use] cmp_lt(self, rhs: Self) -> Self::Output318 fn cmp_lt(self, rhs: Self) -> Self::Output { 319 pick! { 320 if #[cfg(target_feature="sse2")] { 321 Self { sse: cmp_lt_mask_i8_m128i(self.sse, rhs.sse) } 322 } else if #[cfg(target_feature="simd128")] { 323 Self { simd: i8x16_lt(self.simd, rhs.simd) } 324 } else { 325 Self { arr: [ 326 if self.arr[0] < rhs.arr[0] { -1 } else { 0 }, 327 if self.arr[1] < rhs.arr[1] { -1 } else { 0 }, 328 if self.arr[2] < rhs.arr[2] { -1 } else { 0 }, 329 if self.arr[3] < rhs.arr[3] { -1 } else { 0 }, 330 if self.arr[4] < rhs.arr[4] { -1 } else { 0 }, 331 if self.arr[5] < rhs.arr[5] { -1 } else { 0 }, 332 if self.arr[6] < rhs.arr[6] { -1 } else { 0 }, 333 if self.arr[7] < rhs.arr[7] { -1 } else { 0 }, 334 if self.arr[8] < rhs.arr[8] { -1 } else { 0 }, 335 if self.arr[9] < rhs.arr[9] { -1 } else { 0 }, 336 if self.arr[10] < rhs.arr[10] { -1 } else { 0 }, 337 if self.arr[11] < rhs.arr[11] { -1 } else { 0 }, 338 if self.arr[12] < rhs.arr[12] { -1 } else { 0 }, 339 if self.arr[13] < rhs.arr[13] { -1 } else { 0 }, 340 if self.arr[14] < rhs.arr[14] { -1 } else { 0 }, 341 if self.arr[15] < rhs.arr[15] { -1 } else { 0 }, 342 ]} 343 } 344 } 345 } 346 } 347 348 impl i8x16 { 349 #[inline] 350 #[must_use] new(array: [i8; 16]) -> Self351 pub fn new(array: [i8; 16]) -> Self { 352 Self::from(array) 353 } 354 #[inline] 355 #[must_use] blend(self, t: Self, f: Self) -> Self356 pub fn blend(self, t: Self, f: Self) -> Self { 357 pick! { 358 if #[cfg(target_feature="sse4.1")] { 359 Self { sse: blend_varying_i8_m128i(f.sse, t.sse, self.sse) } 360 } else if #[cfg(target_feature="simd128")] { 361 Self { simd: v128_bitselect(t.simd, f.simd, self.simd) } 362 } else { 363 generic_bit_blend(self, t, f) 364 } 365 } 366 } 367 #[inline] 368 #[must_use] abs(self) -> Self369 pub fn abs(self) -> Self { 370 pick! { 371 if #[cfg(target_feature="ssse3")] { 372 Self { sse: abs_i8_m128i(self.sse) } 373 } else if #[cfg(target_feature="simd128")] { 374 Self { simd: i8x16_abs(self.simd) } 375 } else { 376 let arr: [i8; 16] = cast(self); 377 cast([ 378 arr[0].wrapping_abs(), 379 arr[1].wrapping_abs(), 380 arr[2].wrapping_abs(), 381 arr[3].wrapping_abs(), 382 arr[4].wrapping_abs(), 383 arr[5].wrapping_abs(), 384 arr[6].wrapping_abs(), 385 arr[7].wrapping_abs(), 386 arr[8].wrapping_abs(), 387 arr[9].wrapping_abs(), 388 arr[10].wrapping_abs(), 389 arr[11].wrapping_abs(), 390 arr[12].wrapping_abs(), 391 arr[13].wrapping_abs(), 392 arr[14].wrapping_abs(), 393 arr[15].wrapping_abs(), 394 ]) 395 } 396 } 397 } 398 #[inline] 399 #[must_use] max(self, rhs: Self) -> Self400 pub fn max(self, rhs: Self) -> Self { 401 pick! { 402 if #[cfg(target_feature="sse4.1")] { 403 Self { sse: max_i8_m128i(self.sse, rhs.sse) } 404 } else if #[cfg(target_feature="simd128")] { 405 Self { simd: i8x16_max(self.simd, rhs.simd) } 406 } else { 407 self.cmp_lt(rhs).blend(rhs, self) 408 } 409 } 410 } 411 #[inline] 412 #[must_use] min(self, rhs: Self) -> Self413 pub fn min(self, rhs: Self) -> Self { 414 pick! { 415 if #[cfg(target_feature="sse4.1")] { 416 Self { sse: min_i8_m128i(self.sse, rhs.sse) } 417 } else if #[cfg(target_feature="simd128")] { 418 Self { simd: i8x16_min(self.simd, rhs.simd) } 419 } else { 420 self.cmp_lt(rhs).blend(self, rhs) 421 } 422 } 423 } 424 425 #[inline] 426 #[must_use] move_mask(self) -> i32427 pub fn move_mask(self) -> i32 { 428 pick! { 429 if #[cfg(target_feature="sse2")] { 430 move_mask_i8_m128i(self.sse) 431 } else if #[cfg(target_feature="simd128")] { 432 i8x16_bitmask(self.simd) as i32 433 } else { 434 ((self.arr[0] < 0) as i32) << 0 | 435 ((self.arr[1] < 0) as i32) << 1 | 436 ((self.arr[2] < 0) as i32) << 2 | 437 ((self.arr[3] < 0) as i32) << 3 | 438 ((self.arr[4] < 0) as i32) << 4 | 439 ((self.arr[5] < 0) as i32) << 5 | 440 ((self.arr[6] < 0) as i32) << 6 | 441 ((self.arr[7] < 0) as i32) << 7 | 442 ((self.arr[8] < 0) as i32) << 8 | 443 ((self.arr[9] < 0) as i32) << 9 | 444 ((self.arr[10] < 0) as i32) << 10 | 445 ((self.arr[11] < 0) as i32) << 11 | 446 ((self.arr[12] < 0) as i32) << 12 | 447 ((self.arr[13] < 0) as i32) << 13 | 448 ((self.arr[14] < 0) as i32) << 14 | 449 ((self.arr[15] < 0) as i32) << 15 450 } 451 } 452 } 453 #[inline] 454 #[must_use] any(self) -> bool455 pub fn any(self) -> bool { 456 pick! { 457 if #[cfg(target_feature="simd128")] { 458 v128_any_true(self.simd) 459 } else { 460 self.move_mask() != 0 461 } 462 } 463 } 464 #[inline] 465 #[must_use] all(self) -> bool466 pub fn all(self) -> bool { 467 pick! { 468 if #[cfg(target_feature="simd128")] { 469 u8x16_all_true(self.simd) 470 } else { 471 // sixteen lanes 472 self.move_mask() == 0b1111_1111_1111_1111 473 } 474 } 475 } 476 #[inline] 477 #[must_use] none(self) -> bool478 pub fn none(self) -> bool { 479 !self.any() 480 } 481 to_array(self) -> [i8; 16]482 pub fn to_array(self) -> [i8; 16] { 483 cast(self) 484 } 485 as_array_ref(&self) -> &[i8; 16]486 pub fn as_array_ref(&self) -> &[i8; 16] { 487 cast_ref(self) 488 } 489 } 490