Learn Rust the Dangerous Way
head
Copy #include <stdint.h>
#include <stdalign.h>
#include <immintrin.h>
#include <math.h>
#include <stdio.h>
Copy use std::mem;
use std::arch::x86_64::*;
use std::f64::consts::PI;
strcut
Copy // intptr_t should be the native integer type on most
// sane systems.
typedef intptr_t intnative_t;
typedef struct{
double position[3], velocity[3], mass;
} body;
Copy // Note 1
#![allow(
non_upper_case_globals,
non_camel_case_types,
non_snake_case,
)]
#[repr(C)] // Note 2
struct body {
position: [f64; 3],
velocity: [f64; 3],
mass: f64,
}
此allow
属性(类似于 a #pragma
)通知编译器我们希望允许偏离命名约定
#[repr(C)]
标记struct
要求 Rust 布局struct
与 C 完全相同 ,没有的话它会优化它们以获得最佳的打包和对齐——这可能是你以前手工完成的。
Copy #define SOLAR_MASS (4*M_PI*M_PI)
#define DAYS_PER_YEAR 365.24
#define BODIES_COUNT 5
Copy // Note 1
const SOLAR_MASS: f64 = 4. * PI * PI;
const DAYS_PER_YEAR: f64 = 365.24;
const BODIES_COUNT: usize = 5;
#define
s 可以被 Rust 替换const
,它声明了一个常量
函数
Copy static void offset_Momentum(body bodies[]){
for(intnative_t i=0; i<BODIES_COUNT; ++i)
for(intnative_t m=0; m<3; ++m)
bodies[0].velocity[m]-=
bodies[i].velocity[m]*bodies[i].mass/SOLAR_MASS;
}
Copy // v------------------------------------ Note 1
unsafe fn offset_Momentum(bodies: *mut body) {
// ^ ^---- Note 2
for i in 0..BODIES_COUNT { // <---- Note 3
for m in 0..3 {
(*bodies.add(0)).velocity[m] -= // <- Note 4
(*bodies.add(i)).velocity[m] // <- Note 5
* (*bodies.add(i)).mass / SOLAR_MASS;
}
}
}
在 C 中,bodies[i]
完全一样*(bodies + i)
——它执行指针算术和解引用,仅此而已。特别是,它假定您有理由知道这i
是数组的有效索引。这是 C 语言中的常见情况,可以使用方括号进行速记。
在 Rust 中,常见用例使用引用 而不是指针3 并进行边界检查,因此用 例得到简写bodies[i]
。做未经检查的指针算术是例外而不是规则,因此我们必须更加刻意地表达它。
最后,我们必须写*bodies.add(i)
而不是*(bodies + i)
因为 Rust 不会为指针重载算术运算符。相反,指针提供了add
、sub
和其他在代码审查中更容易发现的操作;如果您好奇,这里是完整列表。
Copy static void advance(body bodies[]){
#define INTERACTIONS_COUNT \
(BODIES_COUNT*(BODIES_COUNT-1)/2)
#define ROUNDED_INTERACTIONS_COUNT \
(INTERACTIONS_COUNT+INTERACTIONS_COUNT%2)
// ,--------------------------------- Note 1
// v v-------------------------- Note 2
static alignas(__m128d) double
position_Deltas[3][ROUNDED_INTERACTIONS_COUNT],
magnitudes[ROUNDED_INTERACTIONS_COUNT];
Copy unsafe fn advance(bodies: *mut body) {
const INTERACTIONS_COUNT: usize =
BODIES_COUNT * (BODIES_COUNT - 1) / 2;
const ROUNDED_INTERACTIONS_COUNT: usize =
INTERACTIONS_COUNT + INTERACTIONS_COUNT % 2;
// Note 1
#[repr(align(16))]
#[derive(Copy, Clone)]
struct Align16([f64; ROUNDED_INTERACTIONS_COUNT]);
// Note 2
static mut position_Deltas: [Align16; 3] =
[Align16([0.; ROUNDED_INTERACTIONS_COUNT]); 3];
static mut magnitudes: Align16 =
Align16([0.; ROUNDED_INTERACTIONS_COUNT]);