Daddy needs a new pair of RAM!
edit: the fps are way better in smaller terminal windows with lower character count but then it’s hard to make out the dice. D:
edit2: code here (expires in 2 weeks)
Daddy needs a new pair of RAM!
edit: the fps are way better in smaller terminal windows with lower character count but then it’s hard to make out the dice. D:
edit2: code here (expires in 2 weeks)
Haha nice! How long did it take you? Integer-only math?
All computer math is integer math if you go deep enough
I’m sure implementing floating point directly in bash would work great
I didn’t have the patience to do it myself bit wanted to see just how complex it would get:
fp32_mul() { local a=$1 b=$2 local sa=$(( (a >> 31) & 1 )) local sb=$(( (b >> 31) & 1 )) local sign=$((sa ^ sb)) local ea=$(( (a >> 23) & 0xff )) local eb=$(( (b >> 23) & 0xff )) local fa=$(( a & 0x7fffff )) local fb=$(( b & 0x7fffff )) # NaN / infinity / zero handling if (( ea == 255 )); then if (( fa != 0 )); then printf '%08x\n' $((0x7fc00000)) return fi if (( eb == 0 && fb == 0 )); then printf '%08x\n' $((0x7fc00000)) # inf * 0 = NaN return fi printf '%08x\n' $(((sign << 31) | 0x7f800000)) return fi if (( eb == 255 )); then if (( fb != 0 )); then printf '%08x\n' $((0x7fc00000)) return fi if (( ea == 0 && fa == 0 )); then printf '%08x\n' $((0x7fc00000)) return fi printf '%08x\n' $(((sign << 31) | 0x7f800000)) return fi if (( ea == 0 && fa == 0 || eb == 0 && fb == 0 )); then printf '%08x\n' $((sign << 31)) return fi # Convert subnormals to a normalized significand/exponent. # m is a 24-bit significand for normals. local ma mb if (( ea == 0 )); then ma=$fa ea=1 while (( (ma & 0x800000) == 0 )); do ma=$((ma << 1)) ((ea--)) done else ma=$((fa | 0x800000)) fi if (( eb == 0 )); then mb=$fb eb=1 while (( (mb & 0x800000) == 0 )); do mb=$((mb << 1)) ((eb--)) done else mb=$((fb | 0x800000)) fi # Multiply the two 24-bit significands. # Product is up to 48 bits. local p=$((ma * mb)) local e=$((ea + eb - 127)) # Normalize product. # # ma*mb has binary point after bit 46. If bit 47 is set, # product is [2,4), otherwise [1,2). local shift if (( p & 0x800000000000 )); then shift=24 ((e++)) else shift=23 fi # Extract 23 fraction bits plus guard/round/sticky information. local frac=$(( (p >> shift) & 0x7fffff )) local guard=$(( (p >> (shift - 1)) & 1 )) local round=$(( (p >> (shift - 2)) & 1 )) local sticky=0 if (( shift >= 3 )); then local mask=$(( (1 << (shift - 2)) - 1 )) (( (p & mask) != 0 )) && sticky=1 fi # Round-to-nearest, ties-to-even. if (( guard && (round || sticky || (frac & 1)) )); then ((frac++)) if (( frac == 0x800000 )); then frac=0 ((e++)) fi fi # Overflow -> infinity. if (( e >= 255 )); then printf '%08x\n' $(((sign << 31) | 0x7f800000)) return fi # Normal result. if (( e > 0 )); then printf '%08x\n' $(((sign << 31) | (e << 23) | frac)) return fi # Underflow into the subnormal range. # # At this point the normalized significand represented by # (1.frac) must be shifted right by 1-e positions. local mant=$((0x800000 | frac)) local rshift=$((1 - e)) local lost=0 local halfway=0 local low=0 if (( rshift >= 25 )); then # Everything rounds to zero (unless the exact value is # sufficiently close, which it cannot be here). mant=0 else low=$((mant & ((1 << rshift) - 1))) mant=$((mant >> rshift)) halfway=$((1 << (rshift - 1))) if (( low > halfway || (low == halfway && (mant & 1)) )); then ((mant++)) fi fi # Rounding a subnormal can produce the smallest normal. if (( mant >= 0x800000 )); then printf '%08x\n' $(((sign << 31) | (1 << 23))) else printf '%08x\n' $(((sign << 31) | mant)) fi }1440 multiplications per second on my computer!
Wow, over a kiloflop!
hahaha you seem to be familiar with the issues I ran across
Invert the gravity value and then all the dice will be floating point 🫣
Jebus I don’t even know how long I’ve been working on this. It started out as a way to teach myself bash, combined with my long obsession with rendering platonic solids. I previously coded a huge galaxy of hundreds of thousands of polyhedra you could fly across in python with opengl shaders and got to reuse/translate a lot of that code. The quaternion stuff I was grateful to not have to rethink that much again. haha. And yes, integer-only! Some params are “floating point” but i just parse them and add a bunch of zeroes so i can later do all the operations with equally blown up values of pi and trig stuff from “lookup tables” (case matching).
Btw, you could pipe it to
bcfor the odd float. Or even some complex math. Just in case you didn’t know.yeah, I was trying to stay as pure-bash as possible, but thanks!
Strong Amiga coding vibes.