]> git.proxmox.com Git - rustc.git/blame - src/test/bench/shootout-spectralnorm.rs
Imported Upstream version 1.0.0~beta.3
[rustc.git] / src / test / bench / shootout-spectralnorm.rs
CommitLineData
1a4d82fc
JJ
1// The Computer Language Benchmarks Game
2// http://benchmarksgame.alioth.debian.org/
223e47cc 3//
1a4d82fc
JJ
4// contributed by the Rust Project Developers
5
6// Copyright (c) 2012-2014 The Rust Project Developers
7//
8// All rights reserved.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions
12// are met:
13//
14// - Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// - Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in
19// the documentation and/or other materials provided with the
20// distribution.
21//
22// - Neither the name of "The Computer Language Benchmarks Game" nor
23// the name of "The Computer Language Shootout Benchmarks" nor the
24// names of its contributors may be used to endorse or promote
25// products derived from this software without specific prior
26// written permission.
27//
28// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39// OF THE POSSIBILITY OF SUCH DAMAGE.
40
41// no-pretty-expanded FIXME #15189
42
43#![allow(non_snake_case)]
9346a6ac 44#![feature(unboxed_closures, core, os, scoped)]
1a4d82fc 45
9346a6ac 46use std::iter::repeat;
85aaf69f 47use std::thread;
1a4d82fc 48use std::mem;
970d7e83 49use std::os;
85aaf69f 50use std::env;
1a4d82fc
JJ
51use std::raw::Repr;
52use std::simd::f64x2;
223e47cc 53
1a4d82fc 54fn main() {
85aaf69f
SL
55 let mut args = env::args();
56 let answer = spectralnorm(if env::var_os("RUST_BENCH").is_some() {
1a4d82fc
JJ
57 5500
58 } else if args.len() < 2 {
59 2000
60 } else {
85aaf69f 61 args.nth(1).unwrap().parse().unwrap()
1a4d82fc
JJ
62 });
63 println!("{:.9}", answer);
970d7e83 64}
223e47cc 65
c34b1796 66fn spectralnorm(n: usize) -> f64 {
1a4d82fc
JJ
67 assert!(n % 2 == 0, "only even lengths are accepted");
68 let mut u = repeat(1.0).take(n).collect::<Vec<_>>();
69 let mut v = u.clone();
70 let mut tmp = v.clone();
85aaf69f
SL
71 for _ in 0..10 {
72 mult_AtAv(&u, &mut v, &mut tmp);
73 mult_AtAv(&v, &mut u, &mut tmp);
970d7e83 74 }
85aaf69f 75 (dot(&u, &v) / dot(&v, &v)).sqrt()
223e47cc
LB
76}
77
1a4d82fc
JJ
78fn mult_AtAv(v: &[f64], out: &mut [f64], tmp: &mut [f64]) {
79 mult_Av(v, tmp);
80 mult_Atv(tmp, out);
81}
82
83fn mult_Av(v: &[f64], out: &mut [f64]) {
84 parallel(out, |start, out| mult(v, out, start, |i, j| A(i, j)));
85}
86
87fn mult_Atv(v: &[f64], out: &mut [f64]) {
88 parallel(out, |start, out| mult(v, out, start, |i, j| A(j, i)));
223e47cc
LB
89}
90
c34b1796
AL
91fn mult<F>(v: &[f64], out: &mut [f64], start: usize, a: F)
92 where F: Fn(usize, usize) -> f64 {
1a4d82fc
JJ
93 for (i, slot) in out.iter_mut().enumerate().map(|(i, s)| (i + start, s)) {
94 let mut sum = f64x2(0.0, 0.0);
95 for (j, chunk) in v.chunks(2).enumerate().map(|(j, s)| (2 * j, s)) {
96 let top = f64x2(chunk[0], chunk[1]);
97 let bot = f64x2(a(i, j), a(i, j + 1));
98 sum += top / bot;
223e47cc 99 }
1a4d82fc
JJ
100 let f64x2(a, b) = sum;
101 *slot = a + b;
223e47cc
LB
102 }
103}
104
c34b1796 105fn A(i: usize, j: usize) -> f64 {
1a4d82fc 106 ((i + j) * (i + j + 1) / 2 + i + 1) as f64
223e47cc
LB
107}
108
1a4d82fc
JJ
109fn dot(v: &[f64], u: &[f64]) -> f64 {
110 v.iter().zip(u.iter()).map(|(a, b)| *a * *b).sum()
111}
112
113
1a4d82fc
JJ
114// Executes a closure in parallel over the given mutable slice. The closure `f`
115// is run in parallel and yielded the starting index within `v` as well as a
116// sub-slice of `v`.
85aaf69f
SL
117fn parallel<'a,T, F>(v: &mut [T], ref f: F)
118 where T: Send + Sync + 'a,
c34b1796
AL
119 F: Fn(usize, &mut [T]) + Sync + 'a {
120 // FIXME: pick a more appropriate parallel factor
121 let parallelism = 4;
122 let size = v.len() / parallelism + 1;
1a4d82fc 123 v.chunks_mut(size).enumerate().map(|(i, chunk)| {
85aaf69f
SL
124 thread::scoped(move|| {
125 f(i * size, chunk)
1a4d82fc
JJ
126 })
127 }).collect::<Vec<_>>();
223e47cc 128}