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