5 个版本
使用旧的Rust 2015
0.1.5 | 2015年3月21日 |
---|---|
0.1.4 | 2015年1月26日 |
0.1.3 | 2015年1月4日 |
0.1.1 | 2014年11月20日 |
0.1.0 | 2014年11月14日 |
#865 在 编程语言
每月 29 次下载
15KB
260 行
fractran_macros
一个Rust宏,用于在编译时将嵌入Rust程序中的Fractran程序编译成高效、无分配、仅libcore的代码。
Fractran是一种非常简单的语言;一个程序是一个整数 n
和一系列正分数的列表,通过找到第一个满足 nf
为整数的分数 f
,将 n
替换为 nf
并重复(当没有这样的分数时,执行停止)。结果是,这可以实现图灵完备性,人们甚至用Fractran编写了Fractran解释器!(见 examples/fractran.rs
。)
1没错;您现在可以在内核中使用Fractran了。
使用方法
fractran
宏接受一系列以逗号分隔的算术表达式,表示分数序列。支持的操作
*
、/
和括号用于分组;无算术溢出或精度损失的风险,+
;可能会溢出,- 通过
^
使用整数幂;无溢出,但优先级不正确,所以a^b * c
应为a^(b * c)
,而不是应该的(a^b) * c
。请使用括号以确保正确性。
此宏返回一个构造函数 fn(&[u32]) -> T
,其中 &[u32]
是初始数字(格式如下文所述),而 T
是实现 Iterator<()>
和 fractran_support::Fractran
的类型。调用 next
将执行机器(即找到上述描述的适当分数),当机器停止时返回 None
。
fractran_support::Fractran
特性提供了 state
方法(用于查看当前数字,以指数形式表示)和用于执行状态机直到其停止的 run
方法。
示例
#![feature(phase)]
#[phase(plugin)] extern crate fractran_macros;
fn main() {
// takes 2^a 3^b to 3^(a+b)
let add = fractran!(3/2);
println!("{}", add(&[12, 34]).run()); // [0, 46]
// takes 2^a 3^b to 5^(ab)
let mult = fractran!(455 / 33, 11/13, 1/11, 3/7, 11/2, 1/3);
println!("{}", mult(&[12, 34]).run()); // [0, 0, 408, 0, ...]
}
请确保 Cargo.toml
中有适当的依赖项
[dependencies.fractran_macros]
git = "https://github.com/huonw/fractran_macros"
表示法
数字根据其质因数的(32位)指数表示。数组 [u32]
的第 i
个条目是第 i
个质数的指数(零索引),例如 2 == [1]
,3 == [0, 1]
,9438 == 2 * 3 * 11^2 * 13 == [1, 1, 0, 0, 2, 1]
。这种表示法允许实现处理非常大的数字,任何质数的最大指数都小于 232 的数字,因此最小的不可表示的数字是 2232 = 24294967296。
这也使得内部实现可以非常高效,只需(静态确定的)数组索引和整数比较 & 加法;不存在越界索引的可能性(因此没有从 unwinding 中获得性能惩罚),也没有除法或余数操作。例如,程序 example/prime.rs
使用康威的质数枚举 FRACTRAN 程序生成质数,它只需 6 秒即可执行 10 亿步(达到 887 的壮丽高度)。
可以使用您最喜欢的质数包(例如,使用来自 slow_primes
的质数迭代器)将此表示法转换为实际数字和从实际数字转换到此表示法。
为什么?
为什么不呢?Esolang-macros 很有趣,算术基本定理也很有趣。
依赖关系
~570KB
~11K SLoC