public static ULong BigSqrtRem(ULong lo, UInt hi, out ULong remainder)
 {
     unchecked {
         if (0u == hi)
         {
             return(Mathematics.Elementary.Math.SqrtRem(lo, out remainder));
         }
         var   old = (ULong)Math.Sqrt((0.0 + ((ULong)1u << (Misc.ULong.BitSize - 1)) + ((ULong)1u << (Misc.ULong.BitSize - 1))) * hi + lo);
         ULong h;
         var   l = MathEx.BigSquare(old, out h);
         l += lo;
         h += hi;
         if (l < lo)
         {
             ++h;
         }
         var @new = MathEx.BigDivNoThrow(l, h, old) >> 1;
         l = MathEx.BigSquare(@new, out h);
         if ((h > hi) || ((h == hi) && (l > lo)))
         {
             remainder = lo - l - ((@new << 1) - 1u);
             return(@new - (ULong)1u);
         }
         else
         {
             remainder = lo - l;
             return(@new);
         }
     }
 }
 public static ULong BigSqrt(ULong lo, UInt hi)
 {
     unchecked {
         if (0u == hi)
         {
             return(Mathematics.Elementary.Math.Sqrt(lo));
         }
         var   old = (ULong)Math.Sqrt((0.0 + ((ULong)1u << (ULong_Misc.BitSizeAsIntUnchecked - 1)) + ((ULong)1u << (ULong_Misc.BitSizeAsIntUnchecked - 1))) * hi + lo);
         ULong h;
         var   l = MathEx.BigSquare(old, out h);
         l += lo;
         h += hi;
         if (l < lo)
         {
             ++h;
         }
         var @new = MathEx.BigDivUnchecked(l, h, old) >> 1;
         l = MathEx.BigSquare(@new, out h);
         if ((h > hi) || ((h == hi) && (l > lo)))
         {
             return(@new - (ULong)1u);
         }
         else
         {
             return(@new);
         }
     }
 }
        // ~327. Cyc
        public static ULong SqrtDouble(ULong radicand)
        {
            unchecked {
                if (0u == radicand)
                {
                    return(0u);
                }

                /*
                 * if (radicand <= ~(ULong)0 >> 2) {
                 *  var old = (ULong)(((ULong)1u << (Misc.UInt.BitSize - 0)) * Math.Sqrt(radicand));
                 *  ULong h;
                 *  var l = MathEx.BigSquare(old, out h);
                 *  h += radicand;
                 *  var @new = MathEx.BigDivUnchecked(l, h, old) >> 1;
                 *  l = MathEx.BigSquare(@new, out h);
                 *  if ((h > radicand) || ((h == radicand) && (l > 0u))) {
                 *      return @new - (ULong)1u;
                 *  } else {
                 *      return @new;
                 *  }
                 * }
                 */
                {
                    if (radicand == ~(ULong)0)
                    {
                        return(~(ULong)0);
                    }
                    var old = (ULong)(((ULong)1u << (Misc.UInt.BitSize - 1)) * Math.Sqrt(radicand));
                    var a   = (ULong)0u;
                    var lo  = radicand << (Misc.ULong.BitSize - 2);
                    radicand = radicand >> 2;
                    ULong h;
                    var   l = MathEx.BigSquare(old, out h);
                    l += lo;
                    h += radicand;
                    if (l < lo)
                    {
                        ++h;
                    }
                    var @new = MathEx.BigDivNoThrow(l, h, old) >> 1;
                    l = MathEx.BigSquare(@new, out h);
                    if ((h > radicand) || ((h == radicand) && (l > lo)))
                    {
                        --@new;
                        @new   <<= 1;
                        radicand = (radicand << 2) | (lo >> (Misc.ULong.BitSize - 2));
                        lo       = a;
                        a        = (@new << 1) + 1u;
                        var b = l;
                        l <<= 2;
                        h   = (h << 2) + (ULong)(((l < a) ? -1 : 0) + ((0 > (Long)@new) ? -1 : 0) + ((int)(b >> (Misc.ULong.BitSize - 2))));
                        l  -= a;
                    }
                    else
                    {
                        @new   <<= 1;
                        radicand = (radicand << 2) | (lo >> (Misc.ULong.BitSize - 2));
                        lo       = a;
                        a        = (@new << 1) + 1u;
                        var b = l;
                        l <<= 2;
                        l  += a;
                        h   = (h << 2) + (((l < a) ? 1u : 0u) + ((0 > (Long)@new) ? 1u : 0u) + ((uint)(b >> (Misc.ULong.BitSize - 2))));
                    }
                    if ((h > radicand) || ((h == radicand) && (l > lo)))
                    {
                    }
                    else
                    {
                        ++@new;
                    }
                    return(@new);
                }
            }
        }
 public static ULong BigSqrt(ULong lo, ULong hi)
 {
     unchecked {
         if (0u == hi)
         {
             return(Mathematics.Elementary.Math.Sqrt(lo));
         }
         if (hi <= ~(ULong)0 >> 2)
         {
             var   old = (ULong)Math.Sqrt((0.0 + ((ULong)1u << (Misc.ULong.BitSize - 1)) + ((ULong)1u << (Misc.ULong.BitSize - 1))) * hi + lo);
             ULong h;
             var   l = MathEx.BigSquare(old, out h);
             l += lo;
             h += hi;
             if (l < lo)
             {
                 ++h;
             }
             var @new = MathEx.BigDivNoThrow(l, h, old) >> 1;
             l = MathEx.BigSquare(@new, out h);
             if ((h > hi) || ((h == hi) && (l > lo)))
             {
                 return(@new - (ULong)1u);
             }
             else
             {
                 return(@new);
             }
         }
         {
             if (hi == ~(ULong)0)
             {
                 return(~(ULong)0);
             }
             var old = (ULong)(((ULong)1u << (Misc.UInt.BitSize - 1)) * Math.Sqrt(hi));
             var a   = lo;
             lo = (lo >> 2) | (hi << (Misc.ULong.BitSize - 2));
             hi = hi >> 2;
             ULong h;
             var   l = MathEx.BigSquare(old, out h);
             l += lo;
             h += hi;
             if (l < lo)
             {
                 ++h;
             }
             var @new = MathEx.BigDivNoThrow(l, h, old) >> 1;
             l = MathEx.BigSquare(@new, out h);
             if ((h > hi) || ((h == hi) && (l > lo)))
             {
                 --@new;
                 @new <<= 1;
                 hi     = (hi << 2) | (lo >> (Misc.ULong.BitSize - 2));
                 lo     = a;
                 a      = (@new << 1) + 1u;
                 var b = l;
                 l <<= 2;
                 h   = (h << 2) + (ULong)(((l < a) ? -1 : 0) + ((0 > (Long)@new) ? -1 : 0) + ((int)(b >> (Misc.ULong.BitSize - 2))));
                 l  -= a;
             }
             else
             {
                 @new <<= 1;
                 hi     = (hi << 2) | (lo >> (Misc.ULong.BitSize - 2));
                 lo     = a;
                 a      = (@new << 1) + 1u;
                 var b = l;
                 l <<= 2;
                 l  += a;
                 h   = (h << 2) + (((l < a) ? 1u : 0u) + ((0 > (Long)@new) ? 1u : 0u) + ((uint)(b >> (Misc.ULong.BitSize - 2))));
             }
             if ((h > hi) || ((h == hi) && (l > lo)))
             {
             }
             else
             {
                 ++@new;
             }
             return(@new);
         }
     }
 }