17e102996Smaya/* Compile with: 27e102996Smaya * 37e102996Smaya * glsl_compiler --version 400 --dump-builder int64.glsl > builtin_int64.h 47e102996Smaya * 57e102996Smaya * Version 4.00+ is required for umulExtended. 67e102996Smaya */ 77e102996Smaya#version 400 87e102996Smaya#extension GL_ARB_gpu_shader_int64: require 97e102996Smaya#extension GL_ARB_shading_language_420pack: require 107e102996Smaya 117e102996Smayauvec2 127e102996Smayaumul64(uvec2 a, uvec2 b) 137e102996Smaya{ 147e102996Smaya uvec2 result; 157e102996Smaya 167e102996Smaya umulExtended(a.x, b.x, result.y, result.x); 177e102996Smaya result.y += a.x * b.y + a.y * b.x; 187e102996Smaya 197e102996Smaya return result; 207e102996Smaya} 217e102996Smaya 227e102996Smayaivec2 237e102996Smayasign64(ivec2 a) 247e102996Smaya{ 257e102996Smaya ivec2 result; 267e102996Smaya 277e102996Smaya result.y = a.y >> 31; 287e102996Smaya result.x = result.y | int((a.x | a.y) != 0); 297e102996Smaya 307e102996Smaya return result; 317e102996Smaya} 327e102996Smaya 337e102996Smayauvec4 347e102996Smayaudivmod64(uvec2 n, uvec2 d) 357e102996Smaya{ 367e102996Smaya uvec2 quot = uvec2(0U, 0U); 377e102996Smaya int log2_denom = findMSB(d.y) + 32; 387e102996Smaya 397e102996Smaya /* If the upper 32 bits of denom are non-zero, it is impossible for shifts 407e102996Smaya * greater than 32 bits to occur. If the upper 32 bits of the numerator 417e102996Smaya * are zero, it is impossible for (denom << [63, 32]) <= numer unless 427e102996Smaya * denom == 0. 437e102996Smaya */ 447e102996Smaya if (d.y == 0 && n.y >= d.x) { 457e102996Smaya log2_denom = findMSB(d.x); 467e102996Smaya 477e102996Smaya /* Since the upper 32 bits of denom are zero, log2_denom <= 31 and we 487e102996Smaya * don't have to compare log2_denom inside the loop as is done in the 497e102996Smaya * general case (below). 507e102996Smaya */ 517e102996Smaya for (int i = 31; i >= 1; i--) { 527e102996Smaya if (log2_denom <= 31 - i && (d.x << i) <= n.y) { 537e102996Smaya n.y -= d.x << i; 547e102996Smaya quot.y |= 1U << i; 557e102996Smaya } 567e102996Smaya } 577e102996Smaya 587e102996Smaya /* log2_denom is always <= 31, so manually peel the last loop 597e102996Smaya * iteration. 607e102996Smaya */ 617e102996Smaya if (d.x <= n.y) { 627e102996Smaya n.y -= d.x; 637e102996Smaya quot.y |= 1U; 647e102996Smaya } 657e102996Smaya } 667e102996Smaya 677e102996Smaya uint64_t d64 = packUint2x32(d); 687e102996Smaya uint64_t n64 = packUint2x32(n); 697e102996Smaya for (int i = 31; i >= 1; i--) { 707e102996Smaya if (log2_denom <= 63 - i && (d64 << i) <= n64) { 717e102996Smaya n64 -= d64 << i; 727e102996Smaya quot.x |= 1U << i; 737e102996Smaya } 747e102996Smaya } 757e102996Smaya 767e102996Smaya /* log2_denom is always <= 63, so manually peel the last loop 777e102996Smaya * iteration. 787e102996Smaya */ 797e102996Smaya if (d64 <= n64) { 807e102996Smaya n64 -= d64; 817e102996Smaya quot.x |= 1U; 827e102996Smaya } 837e102996Smaya 847e102996Smaya return uvec4(quot, unpackUint2x32(n64)); 857e102996Smaya} 867e102996Smaya 877e102996Smayauvec2 887e102996Smayaudiv64(uvec2 n, uvec2 d) 897e102996Smaya{ 907e102996Smaya return udivmod64(n, d).xy; 917e102996Smaya} 927e102996Smaya 937e102996Smayaivec2 947e102996Smayaidiv64(ivec2 _n, ivec2 _d) 957e102996Smaya{ 967e102996Smaya const bool negate = (_n.y < 0) != (_d.y < 0); 977e102996Smaya uvec2 n = unpackUint2x32(uint64_t(abs(packInt2x32(_n)))); 987e102996Smaya uvec2 d = unpackUint2x32(uint64_t(abs(packInt2x32(_d)))); 997e102996Smaya 1007e102996Smaya uvec2 quot = udivmod64(n, d).xy; 1017e102996Smaya 1027e102996Smaya return negate ? unpackInt2x32(-int64_t(packUint2x32(quot))) : ivec2(quot); 1037e102996Smaya} 1047e102996Smaya 1057e102996Smayauvec2 1067e102996Smayaumod64(uvec2 n, uvec2 d) 1077e102996Smaya{ 1087e102996Smaya return udivmod64(n, d).zw; 1097e102996Smaya} 1107e102996Smaya 1117e102996Smayaivec2 1127e102996Smayaimod64(ivec2 _n, ivec2 _d) 1137e102996Smaya{ 1147e102996Smaya const bool negate = (_n.y < 0) != (_d.y < 0); 1157e102996Smaya uvec2 n = unpackUint2x32(uint64_t(abs(packInt2x32(_n)))); 1167e102996Smaya uvec2 d = unpackUint2x32(uint64_t(abs(packInt2x32(_d)))); 1177e102996Smaya 1187e102996Smaya uvec2 rem = udivmod64(n, d).zw; 1197e102996Smaya 1207e102996Smaya return negate ? unpackInt2x32(-int64_t(packUint2x32(rem))) : ivec2(rem); 1217e102996Smaya} 122