ary2

Full source code

C++

// -*- mode: c++ -*-
// $Id$
// http://www.bagley.org/~doug/shootout/

#include <cstdlib>
#include <iostream>
#include <vector>

int
main(int argc, char *argv[]) {
#ifdef SMALL_PROBLEM_SIZE
#define LENGTH 90000
#else
#define LENGTH 900000
#endif
    int i, n = 10*((argc == 2) ? atoi(argv[1]) : LENGTH);
    typedef std::vector<int> ARY;
    ARY x(n);
    ARY y(n);

    for (i=0; i<n;) {
        x[i] = i; ++i;
        x[i] = i; ++i;
        x[i] = i; ++i;
        x[i] = i; ++i;
        x[i] = i; ++i;

        x[i] = i; ++i;
        x[i] = i; ++i;
        x[i] = i; ++i;
        x[i] = i; ++i;
        x[i] = i; ++i;
    }
    for (int i = n - 1; i >= 0;) {
        y[i] = x[i]; --i;
        y[i] = x[i]; --i;
        y[i] = x[i]; --i;
        y[i] = x[i]; --i;
        y[i] = x[i]; --i;

        y[i] = x[i]; --i;
        y[i] = x[i]; --i;
        y[i] = x[i]; --i;
        y[i] = x[i]; --i;
        y[i] = x[i]; --i;
    }

    std::cout << y.back() << std::endl;
}

Rust

// Adapted from https://github.com/llvm/llvm-test-suite and
// http://www.bagley.org/~doug/shootout/
use std::env;

#[cfg(feature = "small_problem_size")]
const LENGTH: i32 = 90000;

#[cfg(not(feature = "small_problem_size"))]
const LENGTH: i32 = 900000;

fn main() {
    let mut args = env::args();
    let n = 10 * if args.len() == 2 {
        args.nth(1).unwrap().parse::<i32>().unwrap()
    } else {
        LENGTH
    };

    let mut x = Vec::<i32>::new();
    x.resize(n as usize, 0);
    let mut y = Vec::<i32>::new();
    y.resize(n as usize, 0);

    let mut i: i32 = 0;
    while i < n {
        x[i as usize] = i; i += 1;
        x[i as usize] = i; i += 1;
        x[i as usize] = i; i += 1;
        x[i as usize] = i; i += 1;
        x[i as usize] = i; i += 1;

        x[i as usize] = i; i += 1;
        x[i as usize] = i; i += 1;
        x[i as usize] = i; i += 1;
        x[i as usize] = i; i += 1;
        x[i as usize] = i; i += 1;
    }

    i = n - 1;
    while i >= 0 {
        y[i as usize] = x[i as usize]; i -= 1;
        y[i as usize] = x[i as usize]; i -= 1;
        y[i as usize] = x[i as usize]; i -= 1;
        y[i as usize] = x[i as usize]; i -= 1;
        y[i as usize] = x[i as usize]; i -= 1;

        y[i as usize] = x[i as usize]; i -= 1;
        y[i as usize] = x[i as usize]; i -= 1;
        y[i as usize] = x[i as usize]; i -= 1;
        y[i as usize] = x[i as usize]; i -= 1;
        y[i as usize] = x[i as usize]; i -= 1;
    }

    println!("{}", y.iter().last().unwrap());
}

Porting notes

Using while loops instead of general for loops

C++

    int i, ...
    for (i=0; i<n;) {
      ...
    }
    for (int i = n - 1; i >= 0;) {
      ...
    }

Rust

#![allow(unused)]
fn main() {
    let mut i: i32 = 0;
    while i < n {
      ...
    }
    i = n - 1;
    while i >= 0 {
      ...
    }
}

Since Rust has no general for loops, we use while loops instead.

We declare the loop variable i outside the loop. If we want to explicitly write the type of a local variable, we put the type after the variable name and the : but before the initializer, as in let mut i: i32 = 0;. The type are often omitted relying on type inference.

Incrementing or decrementing a variable

C++

        x[i] = i; ++i;
        ...
        y[i] = x[i]; --i;

Rust

#![allow(unused)]
fn main() {
        x[i as usize] = i; i += 1;
        ...
        y[i as usize] = x[i as usize]; i -= 1;
}

Rust doesn't have the prefix or postfix increment and decrement operators. I think it's to avoid bugs caused by the prefix/postfix evaluation orders. We use the compound assignment operators += and -=.