]> zoso.dev Git - nano-pow.git/commitdiff
Upload bundle.
authorChris Duncan <chris@zoso.dev>
Sat, 1 Mar 2025 07:11:27 +0000 (23:11 -0800)
committerChris Duncan <chris@zoso.dev>
Sat, 1 Mar 2025 07:11:27 +0000 (23:11 -0800)
main.min.js [new file with mode: 0644]

diff --git a/main.min.js b/main.min.js
new file mode 100644 (file)
index 0000000..f6091be
--- /dev/null
@@ -0,0 +1,963 @@
+// src/shaders/compute.wgsl
+var compute_default = "struct UBO{blockhash:array<vec4<u32>,2>,seed:vec2<u32>,threshold:u32};@group(0)@binding(0)var<uniform> ubo:UBO;struct WORK{nonce:vec2<u32>,found:atomic<u32>};@group(0)@binding(1)var<storage,read_write>work:WORK;const BLAKE2B_IV_0=vec2(0xF2BDC900u,0x6A09E667u);const Z=vec2(0u);const CARRY=vec4(1u,0u,1u,0u);const ROTATE_1=vec4(1u);const ROTATE_8=vec4(8u);const ROTATE_16=vec4(16u);const ROTATE_24=vec4(24u);const ROTATE_31=vec4(31u);var<workgroup> found:bool;@compute @workgroup_size(32)fn search(@builtin(global_invocation_id)global_id:vec3<u32>,@builtin(local_invocation_id)local_id:vec3<u32>){found=(local_id.x==0u&&atomicLoad(&work.found)!=0u);workgroupBarrier();if(found){return;}main(global_id);}@compute @workgroup_size(1)fn validate(@builtin(global_invocation_id)global_id:vec3<u32>){main(global_id);}fn main(id:vec3<u32>){let m0:vec2<u32>=ubo.seed ^ id.xy;let m1:vec2<u32>=ubo.blockhash[0u].xy;let m2:vec2<u32>=ubo.blockhash[0u].zw;let m3:vec2<u32>=ubo.blockhash[1u].xy;let m4:vec2<u32>=ubo.blockhash[1u].zw;var v01:vec4<u32>=vec4(BLAKE2B_IV_0,0x84CAA73Bu,0xBB67AE85u);var v23:vec4<u32>=vec4(0xFE94F82Bu,0x3C6EF372u,0x5F1D36F1u,0xA54FF53Au);var v45:vec4<u32>=vec4(0xADE682D1u,0x510E527Fu,0x2B3E6C1Fu,0x9B05688Cu);var v67:vec4<u32>=vec4(0xFB41BD6Bu,0x1F83D9ABu,0x137E2179u,0x5BE0CD19u);var v89:vec4<u32>=vec4(0xF3BCC908u,0x6A09E667u,0x84CAA73Bu,0xBB67AE85u);var vAB:vec4<u32>=vec4(0xFE94F82Bu,0x3C6EF372u,0x5F1D36F1u,0xA54FF53Au);var vCD:vec4<u32>=vec4(0xADE682F9u,0x510E527Fu,0x2B3E6C1Fu,0x9B05688Cu);var vEF:vec4<u32>=vec4(0x04BE4294u,0xE07C2654u,0x137E2179u,0x5BE0CD19u);var v56:vec4<u32>;var vFC:vec4<u32>;var v74:vec4<u32>;var vDE:vec4<u32>;var s0:vec4<u32>;var s1:vec4<u32>;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(m0,m2);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;v23+=vec4(m4,Z);v23.y+=u32(v23.x<m4.x);vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(m1,m3);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m4);v01.w+=u32(v01.z<m4.x);vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(m1,m0);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m2);v01.w+=u32(v01.z<m2.x);v23+=vec4(Z,m3);v23.w+=u32(v23.z<m3.x);vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(Z,m0);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+vec4(m2,Z);v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01.z+=m3.x;v01.w+=m3.y+u32(v01.z<m3.x);vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(m1,m4)+vec4(0u,u32(v23.x+vec4(m1,m4).x<v23.x),0u,u32(v23.z+vec4(m1,m4).z<v23.z));vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m3)+vec4(Z,0u,u32(v01.z+vec4(Z,m3).z<v01.z));vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m1)+vec4(Z,0u,u32(v01.z+vec4(Z,m1).z<v01.z));vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m2,Z)+vec4(0u,u32(v01.x+vec4(m2,Z).x<v01.x),Z);v23+=vec4(m4,Z)+vec4(0u,u32(v23.x+vec4(m4,Z).x<v23.x),Z);vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(m0,Z)+vec4(0u,u32(v23.x+vec4(m0,Z).x<v23.x),Z);vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s1=v23+vec4(m2,Z);v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m0,Z)+vec4(0u,u32(v01.x+vec4(m0,Z).x<v01.x),Z);v23+=vec4(m4,Z)+vec4(0u,u32(v23.x+vec4(m4,Z).x<v23.x),Z);vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s1=v23+vec4(Z,m3);v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m1,Z)+vec4(0u,u32(v01.x+vec4(m1,Z).x<v01.x),Z);vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m2,Z)+vec4(0u,u32(v01.x+vec4(m2,Z).x<v01.x),Z);v23+=vec4(m0,Z)+vec4(0u,u32(v23.x+vec4(m0,Z).x<v23.x),Z);vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s1=v23+vec4(Z,m3);v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m4,Z)+vec4(0u,u32(v01.x+vec4(m4,Z).x<v01.x),Z);v23+=vec4(Z,m1)+vec4(Z,0u,u32(v23.z+vec4(Z,m1).z<v23.z));vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m1)+vec4(Z,0u,u32(v01.z+vec4(Z,m1).z<v01.z));v23+=vec4(Z,m4)+vec4(Z,0u,u32(v23.z+vec4(Z,m4).z<v23.z));vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m0,Z)+vec4(0u,u32(v01.x+vec4(m0,Z).x<v01.x),Z);vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m3)+vec4(Z,0u,u32(v01.z+vec4(Z,m3).z<v01.z));s1=v23+vec4(m2,Z);v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s1=v23+vec4(Z,m3);v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(m1,Z)+vec4(0u,u32(v23.x+vec4(m1,Z).x<v23.x),Z);vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(Z,m2)+vec4(Z,0u,u32(v23.z+vec4(Z,m2).z<v23.z));vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m0,m4)+vec4(0u,u32(v01.x+vec4(m0,m4).x<v01.x),0u,u32(v01.z+vec4(m0,m4).z<v01.z));vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(Z,m0);v23.w+=u32(v23.z<m0.x);vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(m3,Z)+vec4(0u,u32(v23.x+vec4(m3,Z).x<v23.x),Z);vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(m1,Z)+vec4(0u,u32(v23.x+vec4(m1,Z).x<v23.x),Z);vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(m2,Z)+vec4(0u,u32(v01.x+vec4(m2,Z).x<v01.x),Z);v23+=vec4(m4,Z)+vec4(0u,u32(v23.x+vec4(m4,Z).x<v23.x),Z);vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(Z,m1);v23.w+=u32(v23.z<m1.x);vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(m2,m4);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(m3,Z);v23.y+=u32(v23.x<m3.x);vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v23+=vec4(Z,m0);v23.w+=u32(v23.z<m0.x);vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(m0,m2);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;v23+=vec4(m4,Z);v23.y+=u32(v23.x<m4.x);vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(m1,m3);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vFC ^=v01;vFC=(vFC>>ROTATE_16)|(vFC<<ROTATE_16).yxwz;vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_31).yxwz|(v56<<ROTATE_1);v74 ^=v89;v74=(v74>>ROTATE_31).yxwz|(v74<<ROTATE_1);v45=vec4(v74.zw,v56.xy);v67=vec4(v56.zw,v74.xy);vCD=vec4(vFC.zw,vDE.xy);vEF=vec4(vDE.zw,vFC.xy);s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m4);v01.w+=u32(v01.z<m4.x);vCD=(vCD ^ v01).yxwz;vEF=(vEF ^ v23).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_24)|(v45<<ROTATE_8).yxwz;v67 ^=vAB;v67=(v67>>ROTATE_24)|(v67<<ROTATE_8).yxwz;s0=v01+v45;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v67;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;vCD ^=v01;vCD=(vCD>>ROTATE_16)|(vCD<<ROTATE_16).yxwz;vEF ^=v23;vEF=(vEF>>ROTATE_16)|(vEF<<ROTATE_16).yxwz;s0=v89+vCD;v89=s0+(vec4<u32>(s0<v89)&CARRY).yxwz;s1=vAB+vEF;vAB=s1+(vec4<u32>(s1<vAB)&CARRY).yxwz;v45 ^=v89;v45=(v45>>ROTATE_31).yxwz|(v45<<ROTATE_1);v67 ^=vAB;v67=(v67>>ROTATE_31).yxwz|(v67<<ROTATE_1);v56=vec4(v45.zw,v67.xy);v74=vec4(v67.zw,v45.xy);vFC=vec4(vEF.zw,vCD.xy);vDE=vec4(vCD.zw,vEF.xy);s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;s0=v01+vec4(m1,m0);v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;vFC=(vFC ^ v01).yxwz;vDE=(vDE ^ v23).yxwz;s0=vAB+vFC;vAB=s0+(vec4<u32>(s0<vAB)&CARRY).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89)&CARRY).yxwz;v56 ^=vAB;v56=(v56>>ROTATE_24)|(v56<<ROTATE_8).yxwz;v74 ^=v89;v74=(v74>>ROTATE_24)|(v74<<ROTATE_8).yxwz;s0=v01+v56;v01=s0+(vec4<u32>(s0<v01)&CARRY).yxwz;s1=v23+v74;v23=s1+(vec4<u32>(s1<v23)&CARRY).yxwz;v01+=vec4(Z,m2);v01.w+=u32(v01.z<m2.x);v23+=vec4(Z,m3);v23.w+=u32(v23.z<m3.x);vDE ^=v23;vDE=(vDE>>ROTATE_16)|(vDE<<ROTATE_16).yxwz;s1=v89+vDE;v89=s1+(vec4<u32>(s1<v89).yxwz&CARRY);if((BLAKE2B_IV_0.y ^ v01.y ^ v89.y)>ubo.threshold&&atomicLoad(&work.found)==0u){atomicStore(&work.found,1u);work.nonce=m0;}return;}";
+
+// src/shaders/gl-downsample.ts
+var NanoPowGlDownsampleShader = `#version 300 es
+#pragma vscode_glsllint_stage: frag
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+precision highp int;
+
+out uvec4 nonce;
+
+// source texture to be downsampled
+uniform highp usampler2D src;
+
+void main() {
+       nonce = uvec4(0u);
+       vec2 inputSize = vec2(textureSize(src, 0));
+       vec2 texel = vec2(1.0) / inputSize;
+       vec2 blockCoord = (floor(gl_FragCoord.xy) * 2.0 + vec2(0.5)) / inputSize;
+
+       uvec4 pixel = texture(src, blockCoord);
+       nonce = pixel.x == 0u ? nonce : pixel;
+
+       pixel = texture(src, blockCoord + vec2(texel.x, 0.0));
+       nonce = pixel.x == 0u ? nonce : pixel;
+
+       pixel = texture(src, blockCoord + vec2(0.0, texel.y));
+       nonce = pixel.x == 0u ? nonce : pixel;
+
+       pixel = texture(src, blockCoord + vec2(texel.x, texel.y));
+       nonce = pixel.x == 0u ? nonce : pixel;
+}
+`;
+
+// src/shaders/gl-draw.ts
+var NanoPowGlDrawShader = `#version 300 es
+#pragma vscode_glsllint_stage: frag
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+
+out uvec4 nonce;
+
+// blockhash - Array of precalculated block hash components
+// threshold - 0xfffffff8 for send/change blocks, 0xfffffe00 for all else
+// search - Checks all pixels if true, else only checks 1 pixel to validate
+layout(std140) uniform UBO {
+       uint blockhash[8];
+       uint threshold;
+       bool search;
+};
+
+// Random work seed values
+layout(std140) uniform WORK {
+       uvec2 seed;
+};
+
+// Defined separately from uint v[0].y below as the original value is required
+// to calculate the second uint32 of the digest for threshold comparison
+const uint BLAKE2B_IV32_1 = 0x6A09E667u;
+
+// Used during G for vector bit rotations
+const uvec4 ROTATE_1 = uvec4(1u);
+const uvec4 ROTATE_8 = uvec4(8u);
+const uvec4 ROTATE_16 = uvec4(16u);
+const uvec4 ROTATE_24 = uvec4(24u);
+const uvec4 ROTATE_31 = uvec4(31u);
+
+// Both buffers represent 16 uint64s as 32 uint32s
+// because that's what GLSL offers, just like Javascript
+
+// Compression buffer, intialized to 2 instances of the initialization vector
+// The following values have been modified from the BLAKE2B_IV:
+// OUTLEN is constant 8 bytes
+// v[0] ^= 0x01010000u ^ uint(OUTLEN);
+// INLEN is constant 40 bytes: work value (8) + block hash (32)
+// v[12] ^= uint(INLEN);
+// It's always the "last" compression at this INLEN
+// v[14] = ~v[14];
+const uvec2 blake2b_iv[16] = uvec2[16](
+       uvec2(0xF2BDC900u, 0x6A09E667u),
+       uvec2(0x84CAA73Bu, 0xBB67AE85u),
+       uvec2(0xFE94F82Bu, 0x3C6EF372u),
+       uvec2(0x5F1D36F1u, 0xA54FF53Au),
+       uvec2(0xADE682D1u, 0x510E527Fu),
+       uvec2(0x2B3E6C1Fu, 0x9B05688Cu),
+       uvec2(0xFB41BD6Bu, 0x1F83D9ABu),
+       uvec2(0x137E2179u, 0x5BE0CD19u),
+       uvec2(0xF3BCC908u, 0x6A09E667u),
+       uvec2(0x84CAA73Bu, 0xBB67AE85u),
+       uvec2(0xFE94F82Bu, 0x3C6EF372u),
+       uvec2(0x5F1D36F1u, 0xA54FF53Au),
+       uvec2(0xADE682F9u, 0x510E527Fu),
+       uvec2(0x2B3E6C1Fu, 0x9B05688Cu),
+       uvec2(0x04BE4294u, 0xE07C2654u),
+       uvec2(0x137E2179u, 0x5BE0CD19u)
+);
+
+// Iterated initialization vector
+uvec2 v[16];
+
+// Input data buffer
+uvec2 m[16];
+
+// G mixing function, compressing two subprocesses into one
+void G (
+       uint a0, uint b0, uint c0, uint d0, uvec2 x0, uvec2 y0,
+       uint a1, uint b1, uint c1, uint d1, uvec2 x1, uvec2 y1
+) {
+       uvec4 a = uvec4(v[a0], v[a1]);
+       uvec4 b = uvec4(v[b0], v[b1]);
+       uvec4 c = uvec4(v[c0], v[c1]);
+       uvec4 d = uvec4(v[d0], v[d1]);
+       uvec4 mx = uvec4(x0, x1);
+       uvec4 my = uvec4(y0, y1);
+
+       a = a + b + uvec4(0u, uint(a.x + b.x < a.x), 0u, uint(a.z + b.z < a.z));
+       a = a + mx + uvec4(0u, uint(a.x + mx.x < a.x), 0u, uint(a.z + mx.z < a.z));
+       d = (d ^ a).yxwz;
+       c = c + d + uvec4(0u, uint(c.x + d.x < c.x), 0u, uint(c.z + d.z < c.z));
+       b = ((b ^ c) >> ROTATE_24) | ((b ^ c) << ROTATE_8).yxwz;
+       a = a + b + uvec4(0u, uint(a.x + b.x < b.x), 0u, uint(a.z + b.z < b.z));
+       a = a + my + uvec4(0u, uint(a.x + my.x < a.x), 0u, uint(a.z + my.z < a.z));
+       d = ((d ^ a) >> ROTATE_16) | ((d ^ a) << ROTATE_16).yxwz;
+       c = c + d + uvec4(0u, uint(c.x + d.x < c.x), 0u, uint(c.z + d.z < c.z));
+       b = ((b ^ c) >> ROTATE_31).yxwz | ((b ^ c) << ROTATE_1);
+
+       v[a0] = a.xy;
+       v[b0] = b.xy;
+       v[c0] = c.xy;
+       v[d0] = d.xy;
+       v[a1] = a.zw;
+       v[b1] = b.zw;
+       v[c1] = c.zw;
+       v[d1] = d.zw;
+}
+
+void main() {
+       // Initialize fragment output
+       nonce = uvec4(0u);
+
+       // Nonce uniquely differentiated by pixel location
+       m[0u] = seed ^ uvec2(gl_FragCoord);
+
+       // Block hash
+       m[1u] = uvec2(blockhash[0u], blockhash[1u]);
+       m[2u] = uvec2(blockhash[2u], blockhash[3u]);
+       m[3u] = uvec2(blockhash[4u], blockhash[5u]);
+       m[4u] = uvec2(blockhash[6u], blockhash[7u]);
+
+       // Reset v
+       v = blake2b_iv;
+
+       // Twelve rounds of G mixing
+
+       // Round 0
+       G(0u, 4u, 8u, 12u, m[0u], m[1u], 1u, 5u, 9u, 13u, m[2u], m[3u]);
+       G(2u, 6u, 10u, 14u, m[4u], m[5u], 3u, 7u, 11u, 15u, m[6u], m[7u]);
+       G(0u, 5u, 10u, 15u, m[8u], m[9u], 1u, 6u, 11u, 12u, m[10u], m[11u]);
+       G(2u, 7u, 8u, 13u, m[12u], m[13u], 3u, 4u, 9u, 14u, m[14u], m[15u]);
+
+       // Round 1
+       G(0u, 4u, 8u, 12u, m[14u], m[10u], 1u, 5u, 9u, 13u, m[4u], m[8u]);
+       G(2u, 6u, 10u, 14u, m[9u], m[15u], 3u, 7u, 11u, 15u, m[13u], m[6u]);
+       G(0u, 5u, 10u, 15u, m[1u], m[12u], 1u, 6u, 11u, 12u, m[0u], m[2u]);
+       G(2u, 7u, 8u, 13u, m[11u], m[7u], 3u, 4u, 9u, 14u, m[5u], m[3u]);
+
+       // Round 2
+       G(0u, 4u, 8u, 12u, m[11u], m[8u], 1u, 5u, 9u, 13u, m[12u], m[0u]);
+       G(2u, 6u, 10u, 14u, m[5u], m[2u], 3u, 7u, 11u, 15u, m[15u], m[13u]);
+       G(0u, 5u, 10u, 15u, m[10u], m[14u], 1u, 6u, 11u, 12u, m[3u], m[6u]);
+       G(2u, 7u, 8u, 13u, m[7u], m[1u], 3u, 4u, 9u, 14u, m[9u], m[4u]);
+
+       // Round 3
+       G(0u, 4u, 8u, 12u, m[7u], m[9u], 1u, 5u, 9u, 13u, m[3u], m[1u]);
+       G(2u, 6u, 10u, 14u, m[13u], m[12u], 3u, 7u, 11u, 15u, m[11u], m[14u]);
+       G(0u, 5u, 10u, 15u, m[2u], m[6u], 1u, 6u, 11u, 12u, m[5u], m[10u]);
+       G(2u, 7u, 8u, 13u, m[4u], m[0u], 3u, 4u, 9u, 14u, m[15u], m[8u]);
+
+       // Round 4
+       G(0u, 4u, 8u, 12u, m[9u], m[0u], 1u, 5u, 9u, 13u, m[5u], m[7u]);
+       G(2u, 6u, 10u, 14u, m[2u], m[4u], 3u, 7u, 11u, 15u, m[10u], m[15u]);
+       G(0u, 5u, 10u, 15u, m[14u], m[1u], 1u, 6u, 11u, 12u, m[11u], m[12u]);
+       G(2u, 7u, 8u, 13u, m[6u], m[8u], 3u, 4u, 9u, 14u, m[3u], m[13u]);
+
+       // Round 5
+       G(0u, 4u, 8u, 12u, m[2u], m[12u], 1u, 5u, 9u, 13u, m[6u], m[10u]);
+       G(2u, 6u, 10u, 14u, m[0u], m[11u], 3u, 7u, 11u, 15u, m[8u], m[3u]);
+       G(0u, 5u, 10u, 15u, m[4u], m[13u], 1u, 6u, 11u, 12u, m[7u], m[5u]);
+       G(2u, 7u, 8u, 13u, m[15u], m[14u], 3u, 4u, 9u, 14u, m[1u], m[9u]);
+
+       // Round 6
+       G(0u, 4u, 8u, 12u, m[12u], m[5u], 1u, 5u, 9u, 13u, m[1u], m[15u]);
+       G(2u, 6u, 10u, 14u, m[14u], m[13u], 3u, 7u, 11u, 15u, m[4u], m[10u]);
+       G(0u, 5u, 10u, 15u, m[0u], m[7u], 1u, 6u, 11u, 12u, m[6u], m[3u]);
+       G(2u, 7u, 8u, 13u, m[9u], m[2u], 3u, 4u, 9u, 14u, m[8u], m[11u]);
+
+       // Round 7
+       G(0u, 4u, 8u, 12u, m[13u], m[11u], 1u, 5u, 9u, 13u, m[7u], m[14u]);
+       G(2u, 6u, 10u, 14u, m[12u], m[1u], 3u, 7u, 11u, 15u, m[3u], m[9u]);
+       G(0u, 5u, 10u, 15u, m[5u], m[0u], 1u, 6u, 11u, 12u, m[15u], m[4u]);
+       G(2u, 7u, 8u, 13u, m[8u], m[6u], 3u, 4u, 9u, 14u, m[2u], m[10u]);
+
+       // Round 8
+       G(0u, 4u, 8u, 12u, m[6u], m[15u], 1u, 5u, 9u, 13u, m[14u], m[9u]);
+       G(2u, 6u, 10u, 14u, m[11u], m[3u], 3u, 7u, 11u, 15u, m[0u], m[8u]);
+       G(0u, 5u, 10u, 15u, m[12u], m[2u], 1u, 6u, 11u, 12u, m[13u], m[7u]);
+       G(2u, 7u, 8u, 13u, m[1u], m[4u], 3u, 4u, 9u, 14u, m[10u], m[5u]);
+
+       // Round 9
+       G(0u, 4u, 8u, 12u, m[10u], m[2u], 1u, 5u, 9u, 13u, m[8u], m[4u]);
+       G(2u, 6u, 10u, 14u, m[7u], m[6u], 3u, 7u, 11u, 15u, m[1u], m[5u]);
+       G(0u, 5u, 10u, 15u, m[15u], m[11u], 1u, 6u, 11u, 12u, m[9u], m[14u]);
+       G(2u, 7u, 8u, 13u, m[3u], m[12u], 3u, 4u, 9u, 14u, m[13u], m[0u]);
+
+       // Round 10
+       G(0u, 4u, 8u, 12u, m[0u], m[1u], 1u, 5u, 9u, 13u, m[2u], m[3u]);
+       G(2u, 6u, 10u, 14u, m[4u], m[5u], 3u, 7u, 11u, 15u, m[6u], m[7u]);
+       G(0u, 5u, 10u, 15u, m[8u], m[9u], 1u, 6u, 11u, 12u, m[10u], m[11u]);
+       G(2u, 7u, 8u, 13u, m[12u], m[13u], 3u, 4u, 9u, 14u, m[14u], m[15u]);
+
+       // Round 11
+       G(0u, 4u, 8u, 12u, m[14u], m[10u], 1u, 5u, 9u, 13u, m[4u], m[8u]);
+       G(2u, 6u, 10u, 14u, m[9u], m[15u], 3u, 7u, 11u, 15u, m[13u], m[6u]);
+       G(0u, 5u, 10u, 15u, m[1u], m[12u], 1u, 6u, 11u, 12u, m[0u], m[2u]);
+       G(2u, 7u, 8u, 13u, m[11u], m[7u], 3u, 4u, 9u, 14u, m[5u], m[3u]);
+
+       // Pixel data set from work seed values
+       // Finalize digest from high bits, low bits can be safely ignored
+       if ((BLAKE2B_IV32_1 ^ v[0u].y ^ v[8u].y) >= threshold && (search || uvec2(gl_FragCoord) == uvec2(0u))) {
+               nonce = uvec4(1u, m[0u].y, m[0u].x, (uint(gl_FragCoord.x) << 16u) | uint(gl_FragCoord.y));
+       }
+
+       // Valid nonce not found
+       if (nonce.x == 0u) {
+               discard;
+       }
+}
+`;
+
+// src/shaders/gl-vertex.ts
+var NanoPowGlVertexShader = `#version 300 es
+#pragma vscode_glsllint_stage: vert
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+
+layout (location=0) in vec4 position;
+
+void main() {
+       gl_Position = position;
+}
+`;
+
+// src/classes/gl.ts
+var NanoPowGl = class _NanoPowGl {
+  static #busy = false;
+  static #debug = false;
+  static #raf = 0;
+  /** Used to set canvas size. */
+  static #cores = Math.max(1, Math.floor(navigator.hardwareConcurrency));
+  static #WORKLOAD = 256 * this.#cores;
+  static #canvas = new OffscreenCanvas(this.#WORKLOAD, this.#WORKLOAD);
+  static get size() {
+    return this.#gl?.drawingBufferWidth;
+  }
+  static #gl;
+  static #drawProgram;
+  static #downsampleProgram;
+  static #vertexShader;
+  static #drawShader;
+  static #downsampleShader;
+  static #positionBuffer;
+  static #drawFbo;
+  static #downsampleFbos = [];
+  static #downsampleSrcLocation;
+  static #uboBuffer;
+  static #uboView = new DataView(new ArrayBuffer(144));
+  static #seedBuffer;
+  static #seed = new BigUint64Array(1);
+  static #query;
+  static #pixels;
+  /**Vertex Positions, 2 triangles */
+  static #positions = new Float32Array([
+    -1,
+    -1,
+    1,
+    -1,
+    1,
+    1,
+    -1,
+    1
+  ]);
+  /** Compile */
+  static async init() {
+    if (this.#busy) return;
+    this.#busy = true;
+    try {
+      this.#canvas.addEventListener("webglcontextlost", (event) => {
+        event.preventDefault();
+        console.warn("WebGL context lost. Waiting for it to be restored...");
+        cancelAnimationFrame(this.#raf);
+      }, false);
+      this.#canvas.addEventListener("webglcontextrestored", (event) => {
+        console.warn("WebGL context restored. Reinitializing...");
+        _NanoPowGl.init();
+      }, false);
+      this.#gl = this.#canvas.getContext("webgl2");
+      if (this.#gl == null) throw new Error("WebGL 2 is required");
+      this.#drawProgram = this.#gl.createProgram();
+      if (this.#drawProgram == null) throw new Error("Failed to create shader program");
+      this.#vertexShader = this.#gl.createShader(this.#gl.VERTEX_SHADER);
+      if (this.#vertexShader == null) throw new Error("Failed to create vertex shader");
+      this.#gl.shaderSource(this.#vertexShader, NanoPowGlVertexShader);
+      this.#gl.compileShader(this.#vertexShader);
+      if (!this.#gl.getShaderParameter(this.#vertexShader, this.#gl.COMPILE_STATUS))
+        throw new Error(this.#gl.getShaderInfoLog(this.#vertexShader) ?? `Failed to compile vertex shader`);
+      this.#drawShader = this.#gl.createShader(this.#gl.FRAGMENT_SHADER);
+      if (this.#drawShader == null) throw new Error("Failed to create fragment shader");
+      this.#gl.shaderSource(this.#drawShader, NanoPowGlDrawShader);
+      this.#gl.compileShader(this.#drawShader);
+      if (!this.#gl.getShaderParameter(this.#drawShader, this.#gl.COMPILE_STATUS))
+        throw new Error(this.#gl.getShaderInfoLog(this.#drawShader) ?? `Failed to compile fragment shader`);
+      this.#gl.attachShader(this.#drawProgram, this.#vertexShader);
+      this.#gl.attachShader(this.#drawProgram, this.#drawShader);
+      this.#gl.linkProgram(this.#drawProgram);
+      if (!this.#gl.getProgramParameter(this.#drawProgram, this.#gl.LINK_STATUS))
+        throw new Error(this.#gl.getProgramInfoLog(this.#drawProgram) ?? `Failed to link program`);
+      this.#downsampleProgram = this.#gl.createProgram();
+      if (this.#downsampleProgram == null) throw new Error("Failed to create downsample program");
+      this.#downsampleShader = this.#gl.createShader(this.#gl.FRAGMENT_SHADER);
+      if (this.#downsampleShader == null) throw new Error("Failed to create downsample shader");
+      this.#gl.shaderSource(this.#downsampleShader, NanoPowGlDownsampleShader);
+      this.#gl.compileShader(this.#downsampleShader);
+      if (!this.#gl.getShaderParameter(this.#downsampleShader, this.#gl.COMPILE_STATUS))
+        throw new Error(this.#gl.getShaderInfoLog(this.#downsampleShader) ?? `Failed to compile downsample shader`);
+      this.#gl.attachShader(this.#downsampleProgram, this.#vertexShader);
+      this.#gl.attachShader(this.#downsampleProgram, this.#downsampleShader);
+      this.#gl.linkProgram(this.#downsampleProgram);
+      if (!this.#gl.getProgramParameter(this.#downsampleProgram, this.#gl.LINK_STATUS))
+        throw new Error(this.#gl.getProgramInfoLog(this.#downsampleProgram) ?? `Failed to link program`);
+      this.#gl.useProgram(this.#drawProgram);
+      const triangleArray = this.#gl.createVertexArray();
+      this.#gl.bindVertexArray(triangleArray);
+      this.#positionBuffer = this.#gl.createBuffer();
+      this.#gl.bindBuffer(this.#gl.ARRAY_BUFFER, this.#positionBuffer);
+      this.#gl.bufferData(this.#gl.ARRAY_BUFFER, this.#positions, this.#gl.STATIC_DRAW);
+      this.#gl.vertexAttribPointer(0, 2, this.#gl.FLOAT, false, 0, 0);
+      this.#gl.enableVertexAttribArray(0);
+      this.#gl.bindBuffer(this.#gl.ARRAY_BUFFER, null);
+      const texture = this.#gl.createTexture();
+      this.#gl.bindTexture(this.#gl.TEXTURE_2D, texture);
+      this.#gl.texImage2D(this.#gl.TEXTURE_2D, 0, this.#gl.RGBA32UI, this.#gl.drawingBufferWidth, this.#gl.drawingBufferHeight, 0, this.#gl.RGBA_INTEGER, this.#gl.UNSIGNED_INT, null);
+      this.#gl.texParameteri(this.#gl.TEXTURE_2D, this.#gl.TEXTURE_MIN_FILTER, this.#gl.NEAREST);
+      this.#gl.texParameteri(this.#gl.TEXTURE_2D, this.#gl.TEXTURE_MAG_FILTER, this.#gl.NEAREST);
+      const framebuffer = this.#gl.createFramebuffer();
+      this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, framebuffer);
+      this.#gl.framebufferTexture2D(this.#gl.FRAMEBUFFER, this.#gl.COLOR_ATTACHMENT0, this.#gl.TEXTURE_2D, texture, 0);
+      if (this.#gl.checkFramebufferStatus(this.#gl.FRAMEBUFFER) !== this.#gl.FRAMEBUFFER_COMPLETE)
+        throw new Error(`Failed to create drawing framebuffer`);
+      this.#drawFbo = { texture, framebuffer, size: { x: this.#gl.drawingBufferWidth, y: this.#gl.drawingBufferHeight } };
+      for (let i = 1; i <= 4; i++) {
+        const width = this.#gl.drawingBufferWidth / 2 ** i;
+        const height = this.#gl.drawingBufferHeight / 2 ** i;
+        const texture2 = this.#gl.createTexture();
+        this.#gl.bindTexture(this.#gl.TEXTURE_2D, texture2);
+        this.#gl.texImage2D(this.#gl.TEXTURE_2D, 0, this.#gl.RGBA32UI, width, height, 0, this.#gl.RGBA_INTEGER, this.#gl.UNSIGNED_INT, null);
+        this.#gl.texParameteri(this.#gl.TEXTURE_2D, this.#gl.TEXTURE_MIN_FILTER, this.#gl.NEAREST);
+        this.#gl.texParameteri(this.#gl.TEXTURE_2D, this.#gl.TEXTURE_MAG_FILTER, this.#gl.NEAREST);
+        const framebuffer2 = this.#gl.createFramebuffer();
+        this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, framebuffer2);
+        this.#gl.framebufferTexture2D(this.#gl.FRAMEBUFFER, this.#gl.COLOR_ATTACHMENT0, this.#gl.TEXTURE_2D, texture2, 0);
+        if (this.#gl.checkFramebufferStatus(this.#gl.FRAMEBUFFER) !== this.#gl.FRAMEBUFFER_COMPLETE)
+          throw new Error(`Failed to create downsampling framebuffer ${i}`);
+        this.#downsampleFbos.push({ texture: texture2, framebuffer: framebuffer2, size: { x: width, y: height } });
+      }
+      this.#downsampleSrcLocation = this.#gl.getUniformLocation(this.#downsampleProgram, "src");
+      this.#gl.bindTexture(this.#gl.TEXTURE_2D, null);
+      this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, null);
+      this.#uboBuffer = this.#gl.createBuffer();
+      this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#uboBuffer);
+      this.#gl.bufferData(this.#gl.UNIFORM_BUFFER, 144, this.#gl.DYNAMIC_DRAW);
+      this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null);
+      this.#gl.bindBufferBase(this.#gl.UNIFORM_BUFFER, 0, this.#uboBuffer);
+      this.#gl.uniformBlockBinding(this.#drawProgram, this.#gl.getUniformBlockIndex(this.#drawProgram, "UBO"), 0);
+      this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null);
+      this.#seedBuffer = this.#gl.createBuffer();
+      this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#seedBuffer);
+      this.#gl.bufferData(this.#gl.UNIFORM_BUFFER, 16, this.#gl.DYNAMIC_DRAW);
+      this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null);
+      this.#gl.bindBufferBase(this.#gl.UNIFORM_BUFFER, 1, this.#seedBuffer);
+      this.#gl.uniformBlockBinding(this.#drawProgram, this.#gl.getUniformBlockIndex(this.#drawProgram, "WORK"), 1);
+      this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null);
+      this.#query = this.#gl.createQuery();
+      this.#pixels = new Uint32Array(this.#gl.drawingBufferWidth * this.#gl.drawingBufferHeight * 4);
+      console.log(`NanoPow WebGL initialized at ${this.#gl.drawingBufferWidth}x${this.#gl.drawingBufferHeight}. Maximum nonces checked per frame: ${this.#gl.drawingBufferWidth * this.#gl.drawingBufferHeight}`);
+    } catch (err) {
+      throw new Error("WebGL initialization failed.", { cause: err });
+    } finally {
+      this.#busy = false;
+    }
+  }
+  static reset() {
+    cancelAnimationFrame(_NanoPowGl.#raf);
+    _NanoPowGl.#gl?.deleteQuery(_NanoPowGl.#query);
+    _NanoPowGl.#query = null;
+    _NanoPowGl.#gl?.deleteBuffer(_NanoPowGl.#seedBuffer);
+    _NanoPowGl.#seedBuffer = null;
+    _NanoPowGl.#gl?.deleteBuffer(_NanoPowGl.#uboBuffer);
+    _NanoPowGl.#uboBuffer = null;
+    for (const fbo of _NanoPowGl.#downsampleFbos) {
+      _NanoPowGl.#gl?.deleteFramebuffer(fbo.framebuffer);
+      _NanoPowGl.#gl?.deleteTexture(fbo.texture);
+    }
+    _NanoPowGl.#downsampleFbos = [];
+    _NanoPowGl.#gl?.deleteShader(_NanoPowGl.#downsampleShader);
+    _NanoPowGl.#downsampleShader = null;
+    _NanoPowGl.#gl?.deleteProgram(_NanoPowGl.#downsampleProgram);
+    _NanoPowGl.#downsampleProgram = null;
+    _NanoPowGl.#gl?.deleteFramebuffer(_NanoPowGl.#drawFbo?.framebuffer ?? null);
+    _NanoPowGl.#drawFbo = null;
+    _NanoPowGl.#gl?.deleteTexture(_NanoPowGl.#drawFbo);
+    _NanoPowGl.#drawFbo = null;
+    _NanoPowGl.#gl?.deleteBuffer(_NanoPowGl.#positionBuffer);
+    _NanoPowGl.#positionBuffer = null;
+    _NanoPowGl.#gl?.deleteShader(_NanoPowGl.#drawShader);
+    _NanoPowGl.#drawShader = null;
+    _NanoPowGl.#gl?.deleteShader(_NanoPowGl.#vertexShader);
+    _NanoPowGl.#vertexShader = null;
+    _NanoPowGl.#gl?.deleteProgram(_NanoPowGl.#drawProgram);
+    _NanoPowGl.#drawProgram = null;
+    _NanoPowGl.#gl = null;
+    _NanoPowGl.#busy = false;
+    _NanoPowGl.init();
+  }
+  static #logAverages(times) {
+    let count = times.length, sum = 0, reciprocals = 0, logarithms = 0, truncated = 0, min = 65535, max = 0, rate = 0;
+    times.sort();
+    for (let i = 0; i < count; i++) {
+      sum += times[i];
+      reciprocals += 1 / times[i];
+      logarithms += Math.log(times[i]);
+      min = Math.min(min, times[i]);
+      max = Math.max(max, times[i]);
+      if (count < 3 || i > count * 0.1 && i < count * 0.9) truncated += times[i];
+    }
+    const averages = {
+      "Count (frames)": count,
+      "Total (ms)": sum,
+      "Rate (f/s)": 1e3 * count * 0.8 / (truncated || sum),
+      "Minimum (ms)": min,
+      "Maximum (ms)": max,
+      "Arithmetic Mean (ms)": sum / count,
+      "Truncated Mean (ms)": truncated / count,
+      "Harmonic Mean (ms)": count / reciprocals,
+      "Geometric Mean (ms)": Math.exp(logarithms / count)
+    };
+    console.log(`Averages: ${JSON.stringify(averages)}`);
+    console.table(averages);
+  }
+  static #draw(seed) {
+    if (this.#gl == null || this.#query == null) throw new Error("WebGL 2 is required to draw and query pixels");
+    if (this.#drawFbo == null) throw new Error("FBO is required to draw");
+    if (this.#seed[0] == null || this.#seedBuffer == null) throw new Error("Seed is required to draw");
+    this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#seedBuffer);
+    this.#gl.bufferSubData(this.#gl.UNIFORM_BUFFER, 0, seed);
+    this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null);
+    this.#gl.useProgram(this.#drawProgram);
+    this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, this.#drawFbo.framebuffer);
+    this.#gl.activeTexture(this.#gl.TEXTURE0);
+    this.#gl.bindTexture(this.#gl.TEXTURE_2D, this.#drawFbo.texture);
+    this.#gl.beginQuery(this.#gl.ANY_SAMPLES_PASSED_CONSERVATIVE, this.#query);
+    this.#gl.viewport(0, 0, this.#drawFbo.size.x, this.#drawFbo.size.y);
+    this.#gl.drawArrays(this.#gl.TRIANGLES, 0, 4);
+    this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, null);
+    this.#gl.endQuery(this.#gl.ANY_SAMPLES_PASSED_CONSERVATIVE);
+  }
+  static async #checkQueryResult() {
+    return new Promise((resolve, reject) => {
+      function check() {
+        try {
+          if (_NanoPowGl.#gl == null || _NanoPowGl.#query == null) throw new Error("WebGL 2 is required to check query results");
+          if (_NanoPowGl.#gl.getQueryParameter(_NanoPowGl.#query, _NanoPowGl.#gl.QUERY_RESULT_AVAILABLE)) {
+            resolve(!!_NanoPowGl.#gl.getQueryParameter(_NanoPowGl.#query, _NanoPowGl.#gl.QUERY_RESULT));
+          } else {
+            _NanoPowGl.#raf = requestAnimationFrame(check);
+          }
+        } catch (err) {
+          reject(err);
+        }
+      }
+      check();
+    });
+  }
+  /**
+  * Reads pixels into the work buffer, checks every 4th pixel for the 'found'
+  * byte, converts the subsequent 3 pixels with the nonce byte values to a hex
+  * string, and returns the result.
+  *
+  * @param workHex - Original nonce if provided for a validation call
+  * @returns Nonce as an 8-byte (16-char) hexadecimal string
+  */
+  static #readResult(workHex) {
+    if (this.#gl == null) throw new Error("WebGL 2 is required to read pixels");
+    if (this.#drawFbo == null) throw new Error("Source FBO is required to downsample");
+    let source = this.#drawFbo;
+    let pixelCount;
+    const start = performance.now();
+    if (workHex != null) {
+      this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, source.framebuffer);
+      this.#gl.readPixels(0, 0, 1, 1, this.#gl.RGBA_INTEGER, this.#gl.UNSIGNED_INT, this.#pixels);
+      pixelCount = 4;
+    } else {
+      this.#gl.useProgram(this.#downsampleProgram);
+      for (const fbo of this.#downsampleFbos) {
+        this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, fbo.framebuffer);
+        this.#gl.activeTexture(this.#gl.TEXTURE0);
+        this.#gl.bindTexture(this.#gl.TEXTURE_2D, source.texture);
+        this.#gl.uniform1i(this.#downsampleSrcLocation, 0);
+        this.#gl.viewport(0, 0, fbo.size.x, fbo.size.y);
+        this.#gl.drawArrays(this.#gl.TRIANGLES, 0, 4);
+        source = fbo;
+      }
+      this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, source.framebuffer);
+      this.#gl.readPixels(0, 0, source.size.x, source.size.y, this.#gl.RGBA_INTEGER, this.#gl.UNSIGNED_INT, this.#pixels);
+      pixelCount = source.size.x * source.size.y * 4;
+    }
+    this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, null);
+    for (let i = 0; i < pixelCount; i += 4) {
+      if (this.#pixels[i] !== 0) {
+        if (this.#debug) console.log(`readResults (${performance.now() - start} ms)`);
+        if (this.#debug) console.log(`Pixel: rgba(${this.#pixels[i]}, ${this.#pixels[i + 1]}, ${this.#pixels[i + 2]}, ${this.#pixels[i + 3].toString(16).padStart(8, "0")})`);
+        const hex = `${this.#pixels[i + 1].toString(16).padStart(8, "0")}${this.#pixels[i + 2].toString(16).padStart(8, "0")}`;
+        if (workHex == null || workHex == hex) return hex;
+      }
+    }
+    throw new Error("Query reported result but nonce value not found");
+  }
+  /**
+  * Finds a nonce that satisfies the Nano proof-of-work requirements.
+  *
+  * @param {string} hash - Hexadecimal hash of previous block, or public key for new accounts
+  * @param {number} [threshold=0xfffffff8] - Difficulty of proof-of-work calculation
+  */
+  static async search(hash, options) {
+    if (this.#busy) {
+      console.log("NanoPowGl is busy. Retrying search...");
+      return new Promise((resolve) => {
+        setTimeout(async () => {
+          const result = this.search(hash, options);
+          resolve(result);
+        }, 100);
+      });
+    }
+    this.#busy = true;
+    if (!/^[A-Fa-f0-9]{64}$/.test(hash)) throw new Error(`Invalid hash ${hash}`);
+    const threshold = typeof options?.threshold !== "number" || options.threshold < 0 || options.threshold > 4294967295 ? 4294967288 : options.threshold;
+    const effort = typeof options?.effort !== "number" || options.effort < 1 || options.effort > 32 ? this.#cores : options.effort;
+    this.#debug = !!options?.debug;
+    if (this.#WORKLOAD !== 256 * effort) {
+      this.#WORKLOAD = 256 * effort;
+      this.#canvas.height = this.#WORKLOAD;
+      this.#canvas.width = this.#WORKLOAD;
+      this.reset();
+    }
+    if (_NanoPowGl.#gl == null) throw new Error("WebGL 2 is required");
+    if (this.#gl == null) throw new Error("WebGL 2 is required");
+    if (this.#drawFbo == null) throw new Error("WebGL framebuffer is required");
+    this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, this.#drawFbo.framebuffer);
+    this.#gl.clearBufferuiv(this.#gl.COLOR, 0, [0, 0, 0, 0]);
+    this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, null);
+    for (let i = 0; i < this.#uboView.byteLength; i++) this.#uboView.setUint8(i, 0);
+    for (let i = 0; i < 64; i += 8) {
+      const uint32 = hash.slice(i, i + 8);
+      this.#uboView.setUint32(i * 2, parseInt(uint32, 16));
+    }
+    this.#uboView.setUint32(128, threshold, true);
+    this.#uboView.setUint32(132, 1, true);
+    if (this.#debug) console.log("UBO", this.#uboView.buffer.slice(0));
+    this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#uboBuffer);
+    this.#gl.bufferSubData(this.#gl.UNIFORM_BUFFER, 0, this.#uboView);
+    this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null);
+    let times = [];
+    let start = performance.now();
+    let nonce = null;
+    if (this.#debug) console.groupCollapsed("Seeds (click to view)");
+    while (nonce == null) {
+      start = performance.now();
+      const random0 = Math.floor(Math.random() * 4294967295);
+      const random1 = Math.floor(Math.random() * 4294967295);
+      this.#seed[0] = BigInt(random0) << 32n | BigInt(random1);
+      if (this.#debug) console.log("Seed", this.#seed);
+      this.#draw(this.#seed);
+      const found = await this.#checkQueryResult();
+      times.push(performance.now() - start);
+      if (found) {
+        if (this.#debug) console.groupEnd();
+        nonce = this.#readResult();
+      }
+    }
+    this.#busy = false;
+    if (this.#debug) this.#logAverages(times);
+    return nonce;
+  }
+  /**
+  * Validates that a nonce satisfies Nano proof-of-work requirements.
+  *
+  * @param {string} work - Hexadecimal proof-of-work value to validate
+  * @param {string} hash - Hexadecimal hash of previous block, or public key for new accounts
+  * @param {number} [threshold=0xfffffff8] - Difficulty of proof-of-work calculation
+  */
+  static async validate(work, hash, options) {
+    if (this.#busy) {
+      console.log("NanoPowGl is busy. Retrying validate...");
+      return new Promise((resolve) => {
+        setTimeout(async () => {
+          const result = this.validate(work, hash, options);
+          resolve(result);
+        }, 100);
+      });
+    }
+    this.#busy = true;
+    if (!/^[A-Fa-f0-9]{16}$/.test(work)) throw new Error(`Invalid work ${work}`);
+    if (!/^[A-Fa-f0-9]{64}$/.test(hash)) throw new Error(`Invalid hash ${hash}`);
+    const threshold = typeof options?.threshold !== "number" || options.threshold < 0 || options.threshold > 4294967295 ? 4294967288 : options.threshold;
+    this.#debug = !!options?.debug;
+    if (_NanoPowGl.#gl == null) throw new Error("WebGL 2 is required");
+    if (this.#gl == null) throw new Error("WebGL 2 is required");
+    if (this.#drawFbo == null) throw new Error("WebGL framebuffer is required");
+    this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, this.#drawFbo.framebuffer);
+    this.#gl.clearBufferuiv(this.#gl.COLOR, 0, [0, 0, 0, 0]);
+    this.#gl.bindFramebuffer(this.#gl.FRAMEBUFFER, null);
+    for (let i = 0; i < this.#uboView.byteLength; i++) this.#uboView.setUint8(i, 0);
+    for (let i = 0; i < 64; i += 8) {
+      const uint32 = hash.slice(i, i + 8);
+      this.#uboView.setUint32(i * 2, parseInt(uint32, 16));
+    }
+    this.#uboView.setUint32(128, threshold, true);
+    this.#uboView.setUint32(132, 0, true);
+    if (this.#debug) console.log("UBO", this.#uboView.buffer.slice(0));
+    this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, this.#uboBuffer);
+    this.#gl.bufferSubData(this.#gl.UNIFORM_BUFFER, 0, this.#uboView);
+    this.#gl.bindBuffer(this.#gl.UNIFORM_BUFFER, null);
+    let nonce = null;
+    this.#seed[0] = BigInt(`0x${work}`);
+    if (this.#debug) console.log("Work", this.#seed);
+    this.#draw(this.#seed);
+    let found = await this.#checkQueryResult();
+    if (found) {
+      try {
+        nonce = this.#readResult(work);
+      } catch (err) {
+        found = false;
+      }
+    }
+    this.#busy = false;
+    if (found && nonce !== work) throw new Error(`Nonce found but does not match work`);
+    return found;
+  }
+};
+
+// src/classes/gpu.ts
+var NanoPowGpu = class _NanoPowGpu {
+  // Initialize WebGPU
+  static #busy = false;
+  static #debug = false;
+  static #device = null;
+  static #gpuBufferReset = new BigUint64Array([0n, 0n]);
+  static #gpuBuffer;
+  static #cpuBuffer;
+  static #uboBuffer;
+  static #uboView;
+  static #bindGroupLayout;
+  static #searchPipeline;
+  static #validatePipeline;
+  // Initialize WebGPU
+  static async init() {
+    if (this.#busy) return;
+    this.#busy = true;
+    try {
+      if (navigator.gpu == null) throw new Error("WebGPU is not supported in this browser.");
+      const adapter = await navigator.gpu.requestAdapter();
+      if (adapter == null) throw new Error("WebGPU adapter refused by browser.");
+      const device = await adapter.requestDevice();
+      if (!(device instanceof GPUDevice)) throw new Error("WebGPU device failed to load.");
+      device.lost.then(this.reset);
+      this.#device = device;
+      this.setup();
+    } catch (err) {
+      throw new Error("WebGPU initialization failed.", { cause: err });
+    } finally {
+      this.#busy = false;
+    }
+  }
+  static setup() {
+    if (this.#device == null) throw new Error(`WebGPU device failed to load.`);
+    this.#gpuBuffer = this.#device.createBuffer({
+      size: 16,
+      usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC
+    });
+    this.#cpuBuffer = this.#device.createBuffer({
+      size: 16,
+      usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
+    });
+    this.#uboBuffer = this.#device.createBuffer({
+      size: 48,
+      usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
+    });
+    this.#uboView = new DataView(new ArrayBuffer(48));
+    this.#bindGroupLayout = this.#device.createBindGroupLayout({
+      entries: [
+        {
+          binding: 0,
+          visibility: GPUShaderStage.COMPUTE,
+          buffer: { type: "uniform" }
+        },
+        {
+          binding: 1,
+          visibility: GPUShaderStage.COMPUTE,
+          buffer: { type: "storage" }
+        }
+      ]
+    });
+    const shaderModule = this.#device.createShaderModule({
+      code: compute_default
+    });
+    this.#searchPipeline = this.#device.createComputePipeline({
+      layout: this.#device.createPipelineLayout({
+        bindGroupLayouts: [this.#bindGroupLayout]
+      }),
+      compute: {
+        entryPoint: "search",
+        module: shaderModule
+      }
+    });
+    this.#validatePipeline = this.#device.createComputePipeline({
+      layout: this.#device.createPipelineLayout({
+        bindGroupLayouts: [this.#bindGroupLayout]
+      }),
+      compute: {
+        entryPoint: "validate",
+        module: shaderModule
+      }
+    });
+    console.log(`NanoPow WebGPU initialized. Recommended effort: ${Math.max(1, Math.floor(navigator.hardwareConcurrency / 2))}`);
+  }
+  static reset() {
+    console.warn(`GPU device lost. Reinitializing...`);
+    _NanoPowGpu.#cpuBuffer?.destroy();
+    _NanoPowGpu.#gpuBuffer?.destroy();
+    _NanoPowGpu.#uboBuffer?.destroy();
+    _NanoPowGpu.#busy = false;
+    _NanoPowGpu.init();
+  }
+  static #logAverages(times) {
+    let count = times.length, truncatedCount = 0, truncated = 0, sum = 0, reciprocals = 0, logarithms = 0, min = Number.MAX_SAFE_INTEGER, max = 0, median = 0, rate = 0;
+    times.sort();
+    for (let i = 0; i < count; i++) {
+      sum += times[i];
+      reciprocals += 1 / times[i];
+      logarithms += Math.log(times[i]);
+      min = Math.min(min, times[i]);
+      max = Math.max(max, times[i]);
+      if (i === Math.ceil(count / 2)) {
+        median = times[i];
+      }
+      if (count < 3 || i > 0.1 * count && i < 0.9 * (count - 1)) {
+        truncated += times[i];
+        truncatedCount++;
+      }
+    }
+    const averages = {
+      "Count (dispatches)": count,
+      "Total (ms)": sum,
+      "Rate (d/s)": 1e3 * truncatedCount / (truncated || sum),
+      "Minimum (ms)": min,
+      "Maximum (ms)": max,
+      "Median (ms)": median,
+      "Arithmetic Mean (ms)": sum / count,
+      "Truncated Mean (ms)": truncated / truncatedCount,
+      "Harmonic Mean (ms)": count / reciprocals,
+      "Geometric Mean (ms)": Math.exp(logarithms / count)
+    };
+    console.table(averages);
+  }
+  static async #dispatch(pipeline, seed, hash, threshold, passes) {
+    if (this.#device == null) throw new Error(`WebGPU device failed to load.`);
+    for (let i = 0; i < this.#uboView.byteLength; i++) this.#uboView.setUint8(i, 0);
+    for (let i = 0; i < 64; i += 16) {
+      const u64 = hash.slice(i, i + 16);
+      this.#uboView.setBigUint64(i / 2, BigInt(`0x${u64}`));
+    }
+    this.#uboView.setBigUint64(32, seed, true);
+    this.#uboView.setUint32(40, threshold, true);
+    if (this.#debug) console.log("UBO", this.#uboView);
+    this.#device.queue.writeBuffer(this.#uboBuffer, 0, this.#uboView);
+    this.#device.queue.writeBuffer(this.#gpuBuffer, 0, this.#gpuBufferReset);
+    const bindGroup = this.#device.createBindGroup({
+      layout: this.#bindGroupLayout,
+      entries: [
+        {
+          binding: 0,
+          resource: {
+            buffer: this.#uboBuffer
+          }
+        },
+        {
+          binding: 1,
+          resource: {
+            buffer: this.#gpuBuffer
+          }
+        }
+      ]
+    });
+    const commandEncoder = this.#device.createCommandEncoder();
+    const passEncoder = commandEncoder.beginComputePass();
+    passEncoder.setPipeline(pipeline);
+    passEncoder.setBindGroup(0, bindGroup);
+    passEncoder.dispatchWorkgroups(passes, passes);
+    passEncoder.end();
+    commandEncoder.copyBufferToBuffer(this.#gpuBuffer, 0, this.#cpuBuffer, 0, 12);
+    this.#device.queue.submit([commandEncoder.finish()]);
+    let data = null;
+    try {
+      await this.#cpuBuffer.mapAsync(GPUMapMode.READ);
+      await this.#device.queue.onSubmittedWorkDone();
+      data = new DataView(this.#cpuBuffer.getMappedRange().slice(0));
+      this.#cpuBuffer.unmap();
+    } catch (err) {
+      console.warn(`Error getting data from GPU. ${err}`);
+      return this.#dispatch(pipeline, seed, hash, threshold, passes);
+    }
+    if (this.#debug) console.log("gpuBuffer data", data);
+    if (data == null) throw new Error(`Failed to get data from buffer.`);
+    return data;
+  }
+  /**
+  * Finds a nonce that satisfies the Nano proof-of-work requirements.
+  *
+  * @param {string} hash - Hexadecimal hash of previous block, or public key for new accounts
+  * @param {NanoPowOptions} options - Used to configure search execution
+  */
+  static async search(hash, options) {
+    if (!/^[A-Fa-f0-9]{64}$/.test(hash)) throw new TypeError(`Invalid hash ${hash}`);
+    if (this.#busy) {
+      console.log("NanoPowGpu is busy. Retrying search...");
+      return new Promise((resolve) => {
+        setTimeout(async () => {
+          const result = this.search(hash, options);
+          resolve(result);
+        }, 100);
+      });
+    }
+    this.#busy = true;
+    const threshold = typeof options?.threshold !== "number" || options.threshold < 0 || options.threshold > 4294967295 ? 4294967288 : options.threshold;
+    const effort = typeof options?.effort !== "number" || options.effort < 1 || options.effort > 32 ? 2048 : options.effort * 256;
+    this.#debug = !!options?.debug;
+    let loads = 0;
+    while (this.#device == null && loads < 20) {
+      await new Promise((resolve) => {
+        setTimeout(resolve, 500);
+      });
+    }
+    if (this.#device == null) {
+      this.#busy = false;
+      throw new Error(`WebGPU device failed to load.`);
+    }
+    let times = [];
+    let start = performance.now();
+    let nonce = 0n;
+    do {
+      start = performance.now();
+      const random0 = Math.floor(Math.random() * 4294967295);
+      const random1 = Math.floor(Math.random() * 4294967295);
+      const seed = BigInt(random0) << 32n | BigInt(random1);
+      if (this.#debug) console.log(`seed: ${seed}`);
+      const data = await this.#dispatch(this.#searchPipeline, seed, hash, threshold, effort);
+      nonce = data.getBigUint64(0, true);
+      this.#busy = !data.getUint32(8);
+      times.push(performance.now() - start);
+    } while (this.#busy);
+    if (this.#debug) this.#logAverages(times);
+    return nonce.toString(16).padStart(16, "0");
+  }
+  /**
+  * Validates that a nonce satisfies Nano proof-of-work requirements.
+  *
+  * @param {string} work - Hexadecimal proof-of-work value to validate
+  * @param {string} hash - Hexadecimal hash of previous block, or public key for new accounts
+  * @param {NanoPowOptions} options - Options used to configure search execution
+  */
+  static async validate(work, hash, options) {
+    if (!/^[A-Fa-f0-9]{16}$/.test(work)) throw new TypeError(`Invalid work ${work}`);
+    if (!/^[A-Fa-f0-9]{64}$/.test(hash)) throw new TypeError(`Invalid hash ${hash}`);
+    if (this.#busy) {
+      console.log("NanoPowGpu is busy. Retrying validate...");
+      return new Promise((resolve) => {
+        setTimeout(async () => {
+          const result = this.validate(work, hash, options);
+          resolve(result);
+        }, 100);
+      });
+    }
+    this.#busy = true;
+    this.#debug = !!options?.debug;
+    const threshold = typeof options?.threshold !== "number" || options.threshold < 0 || options.threshold > 4294967295 ? 4294967288 : options.threshold;
+    let loads = 0;
+    while (this.#device == null && loads < 20) {
+      await new Promise((resolve) => {
+        setTimeout(resolve, 500);
+      });
+    }
+    if (this.#device == null) {
+      this.#busy = false;
+      throw new Error(`WebGPU device failed to load.`);
+    }
+    const seed = BigInt(`0x${work}`);
+    if (this.#debug) console.log(`work: ${work}`);
+    const data = await this.#dispatch(this.#validatePipeline, seed, hash, threshold, 1);
+    const nonce = data.getBigUint64(0, true).toString(16).padStart(16, "0");
+    if (this.#debug) console.log(`nonce: ${nonce}`);
+    const found = !!data.getUint32(8);
+    this.#busy = false;
+    if (found && work !== nonce) throw new Error(`Nonce (${nonce}) found but does not match work (${work})`);
+    return found;
+  }
+};
+
+// src/classes/index.ts
+var isGlSupported;
+var isGpuSupported = false;
+try {
+  await NanoPowGpu.init();
+  isGpuSupported = true;
+} catch (err) {
+  console.warn("WebGPU is not supported in this environment.\n", err);
+  isGpuSupported = false;
+}
+try {
+  await NanoPowGl.init();
+  isGlSupported = true;
+} catch (err) {
+  console.warn("WebGL is not supported in this environment.\n", err);
+  isGlSupported = false;
+}
+var NanoPow = isGpuSupported ? NanoPowGpu : isGlSupported ? NanoPowGl : null;
+
+// src/main.ts
+var main_default = NanoPow;
+export {
+  NanoPow,
+  NanoPowGl,
+  NanoPowGpu,
+  main_default as default
+};