Skip to content

Instantly share code, notes, and snippets.

@AlexanderHott
Last active December 15, 2024 20:50
Show Gist options
  • Save AlexanderHott/59d130526b5a76079803671ea7d6a115 to your computer and use it in GitHub Desktop.
Save AlexanderHott/59d130526b5a76079803671ea7d6a115 to your computer and use it in GitHub Desktop.
Exercise from [The Little Book of Rust Macros](https://veykril.github.io/tlborm/introduction.html)
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
fn main() {
let fib = {
use std::ops::Index;
const MEM_SIZE: usize = ((0 << 1) | 1) << 1;
{
::std::io::_print(format_args!("1 1+1\n"));
};
struct IndexOffset<'a> {
slice: &'a [u64; MEM_SIZE],
offset: usize,
}
impl<'a> Index<usize> for IndexOffset<'a> {
type Output = u64;
fn index(&self, index: usize) -> &Self::Output {
use std::num::Wrapping;
let index = Wrapping(index);
let offset = Wrapping(self.offset);
let window = Wrapping(MEM_SIZE);
let real_index = index - offset + window;
return &self.slice[real_index.0];
}
}
struct Recurrance {
mem: [u64; MEM_SIZE],
pos: usize,
}
impl Iterator for Recurrance {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
use std::mem::swap;
if self.pos < MEM_SIZE {
let next_val = self.mem[self.pos];
self.pos += 1;
return Some(next_val);
} else {
let n = self.pos;
let a = IndexOffset {
slice: &self.mem,
offset: n,
};
let next_val = a[n - 2] + a[n - 1];
let mut swap_tmp = next_val;
for i in (0..MEM_SIZE).rev() {
swap(&mut swap_tmp, &mut self.mem[i]);
}
self.pos += 1;
return Some(next_val);
}
}
}
Recurrance {
mem: [1, 1 + 1],
pos: 0,
}
};
for e in fib.take(10) {
{
::std::io::_print(format_args!("{0}\n", e));
}
}
let other = {
use std::ops::Index;
const MEM_SIZE: usize = (0 << 1) | 1;
{
::std::io::_print(format_args!("1.0\n"));
};
struct IndexOffset<'a> {
slice: &'a [f64; MEM_SIZE],
offset: usize,
}
impl<'a> Index<usize> for IndexOffset<'a> {
type Output = f64;
fn index(&self, index: usize) -> &Self::Output {
use std::num::Wrapping;
let index = Wrapping(index);
let offset = Wrapping(self.offset);
let window = Wrapping(MEM_SIZE);
let real_index = index - offset + window;
return &self.slice[real_index.0];
}
}
struct Recurrance {
mem: [f64; MEM_SIZE],
pos: usize,
}
impl Iterator for Recurrance {
type Item = f64;
fn next(&mut self) -> Option<Self::Item> {
use std::mem::swap;
if self.pos < MEM_SIZE {
let next_val = self.mem[self.pos];
self.pos += 1;
return Some(next_val);
} else {
let i = self.pos;
let f = IndexOffset {
slice: &self.mem,
offset: i,
};
let next_val = f[i - 1] * i as f64;
let mut swap_tmp = next_val;
for i in (0..MEM_SIZE).rev() {
swap(&mut swap_tmp, &mut self.mem[i]);
}
self.pos += 1;
return Some(next_val);
}
}
}
Recurrance { mem: [1.0], pos: 0 }
};
for e in other.take(10) {
{
::std::io::_print(format_args!("{0}\n", e));
}
}
}
/// Exercise from
/// [The Little Book of Rust Macros](https://veykril.github.io/tlborm/introduction.html)
///
/// View expanded code with `cargo expand`.
/// https://veykril.github.io/tlborm/decl-macros/building-blocks/counting.html#bit-twiddling
macro_rules! count_tts {
() => { 0 };
($odd:tt $($a:tt $b:tt)*) => { (count_tts!($($a)*) << 1) | 1 };
($($a:tt $even:tt)*) => { count_tts!($($a)*) << 1 };
}
macro_rules! recurrence {
( $seq:ident [$idx:ident]: $sty:ty = $($inits:expr),+ ; ... ; $recur:expr) => {{
use std::ops::Index;
const MEM_SIZE: usize = count_tts!($($inits)+);
println!(stringify!($($inits)+));
struct IndexOffset<'a> {
slice: &'a [$sty; MEM_SIZE],
offset: usize,
}
impl<'a> Index<usize> for IndexOffset<'a> {
type Output = $sty;
fn index(&self, index: usize) -> &Self::Output {
use std::num::Wrapping;
let index = Wrapping(index);
let offset = Wrapping(self.offset);
let window = Wrapping(MEM_SIZE);
let real_index = index - offset + window;
return &self.slice[real_index.0];
}
}
struct Recurrance {
mem: [$sty; MEM_SIZE],
pos: usize,
}
impl Iterator for Recurrance {
type Item = $sty;
fn next(&mut self) -> Option<Self::Item> {
use std::mem::swap;
if self.pos < MEM_SIZE {
let next_val = self.mem[self.pos];
self.pos += 1;
return Some(next_val);
} else {
let $idx = self.pos;
let $seq = IndexOffset {
slice: &self.mem,
offset: $idx,
};
let next_val = $recur;
let mut swap_tmp = next_val;
for i in (0..MEM_SIZE).rev() {
swap(&mut swap_tmp, &mut self.mem[i]);
}
self.pos += 1;
return Some(next_val);
}
}
}
Recurrance {
mem: [$($inits),+],
pos: 0,
}
}};
}
fn main() {
let fib = recurrence![a[n]: u64 = 1, 1+1 ; ... ; a[n-2] + a[n-1]];
for e in fib.take(10) {
println!("{}", e)
}
let other = recurrence![f[i]: f64 = 1.0 ; ... ; f[i-1] * i as f64];
for e in other.take(10) {
println!("{}", e)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment