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 a lignas(__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]);