Skip to content

Commit 663cf64

Browse files
gnzlbgBurntSushi
authored andcommitted
implement missing std::ops
1 parent 4d7d2f1 commit 663cf64

File tree

6 files changed

+346
-10
lines changed

6 files changed

+346
-10
lines changed

src/macros.rs

+293-10
Original file line numberDiff line numberDiff line change
@@ -166,20 +166,58 @@ macro_rules! define_common_ops {
166166
unsafe { simd_mul(self, other) }
167167
}
168168
}
169-
)+
170-
}
171-
}
172169

173-
macro_rules! define_float_ops {
174-
($($ty:ident),+) => {
175-
$(
176170
impl ::std::ops::Div for $ty {
177171
type Output = Self;
178172
#[inline(always)]
179173
fn div(self, other: Self) -> Self {
180174
unsafe { simd_div(self, other) }
181175
}
182176
}
177+
178+
impl ::std::ops::Rem for $ty {
179+
type Output = Self;
180+
#[inline(always)]
181+
fn rem(self, other: Self) -> Self {
182+
unsafe { simd_rem(self, other) }
183+
}
184+
}
185+
186+
impl ::std::ops::AddAssign for $ty {
187+
#[inline(always)]
188+
fn add_assign(&mut self, other: Self) {
189+
*self = *self + other;
190+
}
191+
}
192+
193+
impl ::std::ops::SubAssign for $ty {
194+
#[inline(always)]
195+
fn sub_assign(&mut self, other: Self) {
196+
*self = *self - other;
197+
}
198+
}
199+
200+
impl ::std::ops::MulAssign for $ty {
201+
#[inline(always)]
202+
fn mul_assign(&mut self, other: Self) {
203+
*self = *self * other;
204+
}
205+
}
206+
207+
impl ::std::ops::DivAssign for $ty {
208+
#[inline(always)]
209+
fn div_assign(&mut self, other: Self) {
210+
*self = *self / other;
211+
}
212+
}
213+
214+
impl ::std::ops::RemAssign for $ty {
215+
#[inline(always)]
216+
fn rem_assign(&mut self, other: Self) {
217+
*self = *self % other;
218+
}
219+
}
220+
183221
)+
184222
}
185223
}
@@ -201,13 +239,63 @@ macro_rules! define_shifts {
201239
unsafe { simd_shr(self, $ty::splat(other as $elem)) }
202240
}
203241
}
242+
243+
impl ::std::ops::ShlAssign<$by> for $ty {
244+
#[inline(always)]
245+
fn shl_assign(&mut self, other: $by) {
246+
*self = *self << other;
247+
}
248+
}
249+
impl ::std::ops::ShrAssign<$by> for $ty {
250+
#[inline(always)]
251+
fn shr_assign(&mut self, other: $by) {
252+
*self = *self >> other;
253+
}
254+
}
255+
204256
)+
205257
}
206258
}
207259

260+
macro_rules! define_float_ops {
261+
($($ty:ident),+) => {
262+
$(
263+
impl ::std::ops::Neg for $ty {
264+
type Output = Self;
265+
#[inline(always)]
266+
fn neg(self) -> Self {
267+
Self::splat(-1.0) * self
268+
}
269+
}
270+
)+
271+
};
272+
}
273+
274+
macro_rules! define_signed_integer_ops {
275+
($($ty:ident),+) => {
276+
$(
277+
impl ::std::ops::Neg for $ty {
278+
type Output = Self;
279+
#[inline(always)]
280+
fn neg(self) -> Self {
281+
Self::splat(-1) * self
282+
}
283+
}
284+
)+
285+
};
286+
}
287+
208288
macro_rules! define_integer_ops {
209289
($(($ty:ident, $elem:ident)),+) => {
210290
$(
291+
impl ::std::ops::Not for $ty {
292+
type Output = Self;
293+
#[inline(always)]
294+
fn not(self) -> Self {
295+
$ty::splat(!0) ^ self
296+
}
297+
}
298+
211299
impl ::std::ops::BitAnd for $ty {
212300
type Output = Self;
213301
#[inline(always)]
@@ -229,13 +317,25 @@ macro_rules! define_integer_ops {
229317
unsafe { simd_xor(self, other) }
230318
}
231319
}
232-
impl ::std::ops::Not for $ty {
233-
type Output = Self;
320+
impl ::std::ops::BitAndAssign for $ty {
234321
#[inline(always)]
235-
fn not(self) -> Self {
236-
$ty::splat(!0) ^ self
322+
fn bitand_assign(&mut self, other: Self) {
323+
*self = *self & other;
324+
}
325+
}
326+
impl ::std::ops::BitOrAssign for $ty {
327+
#[inline(always)]
328+
fn bitor_assign(&mut self, other: Self) {
329+
*self = *self | other;
330+
}
331+
}
332+
impl ::std::ops::BitXorAssign for $ty {
333+
#[inline(always)]
334+
fn bitxor_assign(&mut self, other: Self) {
335+
*self = *self ^ other;
237336
}
238337
}
338+
239339
define_shifts!(
240340
$ty, $elem,
241341
u8, u16, u32, u64, usize,
@@ -321,3 +421,186 @@ mod tests {
321421
assert!(cfg_feature_enabled!("sse"));
322422
}
323423
}
424+
425+
426+
#[cfg(test)]
427+
#[macro_export]
428+
macro_rules! test_arithmetic_ {
429+
($tn:ident, $zero:expr, $one:expr, $two:expr, $four:expr) => {
430+
{
431+
let z = $tn::splat($zero);
432+
let o = $tn::splat($one);
433+
let t = $tn::splat($two);
434+
let f = $tn::splat($four);
435+
436+
// add
437+
assert_eq!(z + z, z);
438+
assert_eq!(o + z, o);
439+
assert_eq!(t + z, t);
440+
assert_eq!(t + t, f);
441+
// sub
442+
assert_eq!(z - z, z);
443+
assert_eq!(o - z, o);
444+
assert_eq!(t - z, t);
445+
assert_eq!(f - t, t);
446+
assert_eq!(f - o - o, t);
447+
// mul
448+
assert_eq!(z * z, z);
449+
assert_eq!(z * o, z);
450+
assert_eq!(z * t, z);
451+
assert_eq!(o * t, t);
452+
assert_eq!(t * t, f);
453+
// div
454+
assert_eq!(z / o, z);
455+
assert_eq!(t / o, t);
456+
assert_eq!(f / o, f);
457+
assert_eq!(t / t, o);
458+
assert_eq!(f / t, t);
459+
// rem
460+
assert_eq!(o % o, z);
461+
assert_eq!(f % t, z);
462+
463+
{
464+
let mut v = z;
465+
assert_eq!(v, z);
466+
v += o; // add_assign
467+
assert_eq!(v, o);
468+
v -= o; // sub_assign
469+
assert_eq!(v, z);
470+
v = t;
471+
v *= o; // mul_assign
472+
assert_eq!(v, t);
473+
v *= t;
474+
assert_eq!(v, f);
475+
v /= o; // div_assign
476+
assert_eq!(v, f);
477+
v /= t;
478+
assert_eq!(v, t);
479+
v %= t; // rem_assign
480+
assert_eq!(v, z);
481+
}
482+
}
483+
};
484+
}
485+
486+
#[cfg(test)]
487+
#[macro_export]
488+
macro_rules! test_neg_ {
489+
($tn:ident, $zero:expr, $one:expr, $two:expr, $four:expr) => {
490+
{
491+
let z = $tn::splat($zero);
492+
let o = $tn::splat($one);
493+
let t = $tn::splat($two);
494+
let f = $tn::splat($four);
495+
496+
let nz = $tn::splat(-$zero);
497+
let no = $tn::splat(-$one);
498+
let nt = $tn::splat(-$two);
499+
let nf = $tn::splat(-$four);
500+
501+
assert_eq!(-z, nz);
502+
assert_eq!(-o, no);
503+
assert_eq!(-t, nt);
504+
assert_eq!(-f, nf);
505+
}
506+
};
507+
}
508+
509+
#[cfg(test)]
510+
#[macro_export]
511+
macro_rules! test_bit_arithmetic_ {
512+
($tn:ident) => {
513+
{
514+
let z = $tn::splat(0);
515+
let o = $tn::splat(1);
516+
let t = $tn::splat(2);
517+
let f = $tn::splat(4);
518+
let m = $tn::splat(!z.extract(0));
519+
520+
// shr
521+
assert_eq!(o >> 1, z);
522+
assert_eq!(t >> 1, o);
523+
assert_eq!(f >> 1, t);
524+
// shl
525+
assert_eq!(o << 1, t);
526+
assert_eq!(o << 2, f);
527+
assert_eq!(t << 1, f);
528+
// bitand
529+
assert_eq!(o & o, o);
530+
assert_eq!(t & t, t);
531+
assert_eq!(t & o, z);
532+
// bitor
533+
assert_eq!(o | o, o);
534+
assert_eq!(t | t, t);
535+
assert_eq!(z | o, o);
536+
// bitxor
537+
assert_eq!(o ^ o, z);
538+
assert_eq!(t ^ t, z);
539+
assert_eq!(z ^ o, o);
540+
// not
541+
assert_eq!(!z, m);
542+
assert_eq!(!m, z);
543+
544+
{ // shr_assign
545+
let mut v = o;
546+
v >>= 1;
547+
assert_eq!(v, z);
548+
}
549+
{ // shl_assign
550+
let mut v = o;
551+
v <<= 1;
552+
assert_eq!(v, t);
553+
}
554+
{ // and_assign
555+
let mut v = o;
556+
v &= t;
557+
assert_eq!(v, z);
558+
}
559+
{ // or_assign
560+
let mut v = z;
561+
v |= o;
562+
assert_eq!(v, o);
563+
}
564+
{ // xor_assign
565+
let mut v = z;
566+
v ^= o;
567+
assert_eq!(v, o);
568+
}
569+
}
570+
};
571+
}
572+
573+
574+
#[cfg(test)]
575+
#[macro_export]
576+
macro_rules! test_ops_si {
577+
($($tn:ident),+) => {
578+
$(
579+
test_arithmetic_!($tn, 0, 1, 2, 4);
580+
test_neg_!($tn, 0, 1, 2, 4);
581+
test_bit_arithmetic_!($tn);
582+
)+
583+
};
584+
}
585+
586+
#[cfg(test)]
587+
#[macro_export]
588+
macro_rules! test_ops_ui {
589+
($($tn:ident),+) => {
590+
$(
591+
test_arithmetic_!($tn, 0, 1, 2, 4);
592+
test_bit_arithmetic_!($tn);
593+
)+
594+
};
595+
}
596+
597+
#[cfg(test)]
598+
#[macro_export]
599+
macro_rules! test_ops_f {
600+
($($tn:ident),+) => {
601+
$(
602+
test_arithmetic_!($tn, 0., 1., 2., 4.);
603+
test_neg_!($tn, 0., 1., 2., 4.);
604+
)+
605+
};
606+
}

src/simd_llvm.rs

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ extern "platform-intrinsic" {
2525
pub fn simd_sub<T>(x: T, y: T) -> T;
2626
pub fn simd_mul<T>(x: T, y: T) -> T;
2727
pub fn simd_div<T>(x: T, y: T) -> T;
28+
pub fn simd_rem<T>(x: T, y: T) -> T;
2829
pub fn simd_shl<T>(x: T, y: T) -> T;
2930
pub fn simd_shr<T>(x: T, y: T) -> T;
3031
pub fn simd_and<T>(x: T, y: T) -> T;

src/v128.rs

+13
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ define_integer_ops!(
7474
(u8x16, u8),
7575
(i8x16, i8)
7676
);
77+
define_signed_integer_ops!(i64x2, i32x4, i16x8, i8x16);
7778
define_casts!(
7879
(f64x2, f32x2, as_f32x2),
7980
(f64x2, u64x2, as_u64x2),
@@ -94,3 +95,15 @@ define_casts!(
9495
(u8x16, i8x16, as_i8x16),
9596
(i8x16, u8x16, as_u8x16)
9697
);
98+
99+
#[cfg(test)]
100+
mod tests {
101+
use super::*;
102+
103+
#[test]
104+
fn operators() {
105+
test_ops_si!(i8x16, i16x8, i32x4, i64x2);
106+
test_ops_ui!(u8x16, u16x8, u32x4, u64x2);
107+
test_ops_f!(f32x4, f64x2);
108+
}
109+
}

0 commit comments

Comments
 (0)