u235.rs (6017B)
1 //! ```cargo 2 //! [dependencies] 3 //! bnum = "0.3.0" 4 //! num-traits = "0.2.15" 5 //! rand = "0.8.5" 6 //! rand_distr = "0.4.3" 7 //! ``` 8 9 /// Editor's note: a pretty silly joke library based on a pun. 10 /// Written on December 21, 2022. 11 12 use std::time::{Instant, Duration}; 13 use bnum::cast::{As, CastFrom}; 14 use bnum::BUintD8; 15 use rand::prelude::*; 16 use rand_distr::StandardNormal; 17 18 const HALF_LIFE: f64 = 703_800_000.0; 19 const RADIATION_REACH: usize = 2 * 8; 20 21 22 #[allow(non_camel_case_types)] 23 #[repr(C)] 24 pub struct u235 { 25 value: BUintD8<30>, 26 updated: Instant, 27 } 28 29 struct Hazmat<const P: usize, T: std::default::Default> { 30 pad1: [u8; P], 31 item: T, 32 pad2: [u8; P], 33 } 34 35 impl<const P: usize, T: std::default::Default> Hazmat<P, T> { 36 fn contain(&mut self, thing: T) { 37 self.item = thing; 38 } 39 40 fn item(&mut self) -> &mut T { 41 &mut self.item 42 } 43 } 44 45 type OkHazmat<T> = Hazmat<RADIATION_REACH, T>; 46 47 struct HazmatManufacturer; 48 impl HazmatManufacturer { 49 fn ok_hazmat<T: std::default::Default>() -> OkHazmat<T> { 50 Hazmat { 51 pad1: [0; RADIATION_REACH], 52 item: T::default(), 53 pad2: [0; RADIATION_REACH], 54 } 55 } 56 57 fn good_hazmat<T: std::default::Default>() -> Hazmat<{2*RADIATION_REACH}, T> { 58 Hazmat { 59 pad1: [0; 2*RADIATION_REACH], 60 item: T::default(), 61 pad2: [0; 2*RADIATION_REACH], 62 } 63 } 64 65 fn great_hazmat<T: std::default::Default>() -> Hazmat<{3*RADIATION_REACH}, T> { 66 Hazmat { 67 pad1: [0; 3*RADIATION_REACH], 68 item: T::default(), 69 pad2: [0; 3*RADIATION_REACH], 70 } 71 } 72 } 73 74 impl u235 { 75 fn max() -> u235 { 76 u235 { 77 value: BUintD8::from(2u64).pow(235) - BUintD8::from(1u64), 78 updated: Instant::now(), 79 } 80 } 81 82 fn new(val: u64) -> u235 { 83 let ret = u235 { 84 value: BUintD8::from(val), 85 updated: Instant::now(), 86 }; 87 if cfg!(feature = "ambient-radiation") { 88 let this = &ret as *const u235 as *mut u235 as u64; 89 std::thread::spawn(move || unsafe { 90 loop { 91 (*(this as *mut u235)).radiate(); 92 } 93 }); 94 } 95 std::thread::sleep(Duration::from_secs(2)); 96 ret 97 } 98 99 unsafe fn this(&self) -> &mut Self { 100 &mut *(self as *const Self as *mut Self) 101 } 102 103 unsafe fn dump_nearby_stack(&self, range: usize, show_self: bool) { 104 // let now = Instant::now(); 105 // let nowptr = &now as *const Instant as *mut Instant as *mut u8; 106 let ptr = self as *const Self as *mut Self; 107 let left = ptr.add(1) as *mut u8; 108 let right = ptr as *mut u8; 109 println!("{}", std::mem::size_of::<u235>()); 110 for i in 0..range { 111 println!("{:08b}", *left.add(range-i)); 112 } 113 println!(" (U235) "); 114 if show_self { 115 for i in 0..std::mem::size_of::<u235>() { 116 println!("{:08b}", *right.sub(1).add(i)); 117 } 118 println!(" (U235) "); 119 } 120 for i in 0..range { 121 println!("{:08b}", *right.sub(i)); 122 } 123 println!() 124 } 125 126 unsafe fn decay(&self) { 127 let now = Instant::now(); 128 let t = (now - self.updated).as_nanos(); 129 let this = self.this(); 130 this.value = BUintD8::cast_from( 131 self.value.as_::<f64>() * (0.5f64.powf(t as f64/HALF_LIFE)) 132 ); 133 this.updated = now; 134 } 135 136 unsafe fn radiate(&self) { 137 let ptr = self as *const Self as *mut u8; 138 let val: f64 = thread_rng().sample(StandardNormal); 139 let off: isize = (val * RADIATION_REACH as f64).round() as isize; 140 println!("Flipping bit {off}"); 141 if off < 0 { 142 let shift = if (off%8).abs() == 0 { 0 } else { 8 - (off%8).abs() }; 143 *ptr.add(((off+1)/8) as usize) ^= 1 << shift; 144 } else if off > 0 { 145 let (byte, shift) = if (off%8).abs() == 0 { 146 ((off/8) as usize, 7) 147 } else { ((off/8 + 1) as usize, (off%8).abs()-1) }; 148 *ptr.add(std::mem::size_of::<u235>()).add(byte) ^= 1 << shift; 149 }; 150 } 151 152 unsafe fn assert_value(&self, val: u64) { 153 self.decay(); 154 assert_eq!(self.value, BUintD8::from(val)) 155 } 156 157 unsafe fn to_u64(&self) -> u64 { 158 self.decay(); 159 self.value.as_::<u64>() 160 } 161 } 162 163 impl core::ops::Rem for u235 { 164 type Output = Self; 165 fn rem(self, other: Self) -> Self { 166 unsafe { 167 self.decay(); 168 Self {value: self.value % other.value, updated: self.updated} 169 } 170 } 171 } 172 173 impl core::ops::Add for u235 { 174 type Output = Self; 175 fn add(self, other: Self) -> Self { 176 unsafe { 177 self.decay(); 178 Self { 179 value: (self.value + other.value) % Self::max().value, 180 updated: self.updated 181 } 182 } 183 } 184 } 185 186 impl core::ops::Sub for u235 { 187 type Output = Self; 188 fn sub(self, other: Self) -> Self { 189 unsafe { 190 self.decay(); 191 Self {value: self.value - other.value, updated: self.updated} 192 } 193 } 194 } 195 196 impl core::cmp::PartialEq for u235 { 197 fn eq(&self, other: &Self) -> bool { 198 unsafe { 199 self.decay(); 200 other.decay(); 201 self.value == other.value 202 } 203 } 204 } 205 206 impl std::fmt::Debug for u235 { 207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 208 f.write_str(&format!("{:?}", self.value)) 209 } 210 } 211 212 impl std::default::Default for u235 { 213 fn default() -> Self { 214 u235::new(0) 215 } 216 } 217 218 fn main() { 219 use std::thread; 220 use std::time::Duration; 221 222 unsafe { 223 let x = u235::new(32); 224 assert!(x.to_u64() > 0); 225 thread::sleep(Duration::from_secs(1)); 226 assert!(x.to_u64() > 0); 227 thread::sleep(Duration::from_secs(1)); 228 assert_eq!(x.to_u64(), 0); 229 } 230 }