]> git.proxmox.com Git - rustc.git/blame - src/test/run-pass/simd-intrinsic-generic-cast.rs
New upstream version 1.14.0+dfsg1
[rustc.git] / src / test / run-pass / simd-intrinsic-generic-cast.rs
CommitLineData
e9174d1e
SL
1// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
c30ab7b3 10// ignore-emscripten linking with emcc failed
e9174d1e 11
9e0c209e 12#![feature(repr_simd, platform_intrinsics, concat_idents, test)]
e9174d1e
SL
13#![allow(non_camel_case_types)]
14
15extern crate test;
16
17#[repr(simd)]
18#[derive(PartialEq, Debug)]
19struct i32x4(i32, i32, i32, i32);
20#[repr(simd)]
21#[derive(PartialEq, Debug)]
22struct i8x4(i8, i8, i8, i8);
23
24#[repr(simd)]
25#[derive(PartialEq, Debug)]
26struct u32x4(u32, u32, u32, u32);
27#[repr(simd)]
28#[derive(PartialEq, Debug)]
29struct u8x4(u8, u8, u8, u8);
30
31#[repr(simd)]
32#[derive(PartialEq, Debug)]
33struct f32x4(f32, f32, f32, f32);
34
35#[repr(simd)]
36#[derive(PartialEq, Debug)]
37struct f64x4(f64, f64, f64, f64);
38
39
40extern "platform-intrinsic" {
41 fn simd_cast<T, U>(x: T) -> U;
42}
43
44const A: i32 = -1234567;
45const B: i32 = 12345678;
46const C: i32 = -123456789;
47const D: i32 = 1234567890;
48
49trait Foo {
50 fn is_float() -> bool { false }
51 fn in_range(x: i32) -> bool;
52}
53impl Foo for i32 {
54 fn in_range(_: i32) -> bool { true }
55}
56impl Foo for i8 {
57 fn in_range(x: i32) -> bool { -128 <= x && x < 128 }
58}
59impl Foo for u32 {
60 fn in_range(x: i32) -> bool { 0 <= x }
61}
62impl Foo for u8 {
63 fn in_range(x: i32) -> bool { 0 <= x && x < 128 }
64}
65impl Foo for f32 {
66 fn is_float() -> bool { true }
67 fn in_range(_: i32) -> bool { true }
68}
69impl Foo for f64 {
70 fn is_float() -> bool { true }
71 fn in_range(_: i32) -> bool { true }
72}
73
74fn main() {
75 macro_rules! test {
76 ($from: ident, $to: ident) => {{
77 // force the casts to actually happen, or else LLVM/rustc
78 // may fold them and get slightly different results.
79 let (a, b, c, d) = test::black_box((A as $from, B as $from, C as $from, D as $from));
80 // the SIMD vectors are all FOOx4, so we can concat_idents
81 // so we don't have to pass in the extra args to the macro
82 let mut from = simd_cast(concat_idents!($from, x4)(a, b, c, d));
83 let mut to = concat_idents!($to, x4)(a as $to,
84 b as $to,
85 c as $to,
86 d as $to);
87 // assist type inference, it needs to know what `from` is
88 // for the `if` statements.
89 to == from;
90
91 // there are platform differences for some out of range
92 // casts, so we just normalize such things: it's OK for
93 // "invalid" calculations to result in nonsense answers.
94 // (E.g. negative float to unsigned integer goes through a
95 // library routine on the default i686 platforms, and the
96 // implementation of that routine differs on e.g. Linux
97 // vs. OSX, resulting in different answers.)
98 if $from::is_float() {
99 if !$to::in_range(A) { from.0 = 0 as $to; to.0 = 0 as $to; }
100 if !$to::in_range(B) { from.1 = 0 as $to; to.1 = 0 as $to; }
101 if !$to::in_range(C) { from.2 = 0 as $to; to.2 = 0 as $to; }
102 if !$to::in_range(D) { from.3 = 0 as $to; to.3 = 0 as $to; }
103 }
104
105 assert!(to == from,
106 "{} -> {} ({:?} != {:?})", stringify!($from), stringify!($to),
107 from, to);
108 }}
109 }
110 macro_rules! tests {
111 (: $($to: ident),*) => { () };
112 // repeating the list twice is easier than writing a cartesian
113 // product macro
114 ($from: ident $(, $from_: ident)*: $($to: ident),*) => {
115 fn $from() { unsafe { $( test!($from, $to); )* } }
116 tests!($($from_),*: $($to),*)
117 };
118 ($($types: ident),*) => {{
119 tests!($($types),* : $($types),*);
120 $($types();)*
121 }}
122 }
123
124 // test various combinations, including truncation,
125 // signed/unsigned extension, and floating point casts.
126 tests!(i32, i8, u32, u8, f32);
127 tests!(i32, u32, f32, f64)
128}