hacks

(tidier examples of) random scripts from throughout the years
Log | Files | Refs | README

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 }