Skip to content

Commit 4b2a618

Browse files
committed
implement missing std::ops
1 parent 4c244fb commit 4b2a618

File tree

6 files changed

+348
-10
lines changed

6 files changed

+348
-10
lines changed

src/macros.rs

+295-10
Original file line numberDiff line numberDiff line change
@@ -166,20 +166,60 @@ 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) }
175+
other
176+
}
177+
}
178+
179+
impl ::std::ops::Rem for $ty {
180+
type Output = Self;
181+
#[inline(always)]
182+
fn rem(self, other: Self) -> Self {
183+
unsafe { simd_rem(self, other) }
184+
other
185+
}
186+
}
187+
188+
impl ::std::ops::AddAssign for $ty {
189+
#[inline(always)]
190+
fn add_assign(&mut self, other: Self) {
191+
*self = *self + other;
192+
}
193+
}
194+
195+
impl ::std::ops::SubAssign for $ty {
196+
#[inline(always)]
197+
fn sub_assign(&mut self, other: Self) {
198+
*self = *self - other;
199+
}
200+
}
201+
202+
impl ::std::ops::MulAssign for $ty {
203+
#[inline(always)]
204+
fn mul_assign(&mut self, other: Self) {
205+
*self = *self * other;
206+
}
207+
}
208+
209+
impl ::std::ops::DivAssign for $ty {
210+
#[inline(always)]
211+
fn div_assign(&mut self, other: Self) {
212+
*self = *self / other;
213+
}
214+
}
215+
216+
impl ::std::ops::RemAssign for $ty {
217+
#[inline(always)]
218+
fn rem_assign(&mut self, other: Self) {
219+
*self = *self % other;
181220
}
182221
}
222+
183223
)+
184224
}
185225
}
@@ -201,13 +241,63 @@ macro_rules! define_shifts {
201241
unsafe { simd_shr(self, $ty::splat(other as $elem)) }
202242
}
203243
}
244+
245+
impl ::std::ops::ShlAssign<$by> for $ty {
246+
#[inline(always)]
247+
fn shl_assign(&mut self, other: $by) {
248+
*self = *self << other;
249+
}
250+
}
251+
impl ::std::ops::ShrAssign<$by> for $ty {
252+
#[inline(always)]
253+
fn shr_assign(&mut self, other: $by) {
254+
*self = *self >> other;
255+
}
256+
}
257+
204258
)+
205259
}
206260
}
207261

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

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)