#if !defined  HAVE_BINARYGCD_H__
#define       HAVE_BINARYGCD_H__

#include "aux0/swap.h"
#include "fxttypes.h"  // ulong


template <typename Type>
Type binary_ugcd(Type a, Type b)
// Return greatest common divisor of a and b.
// Version for unsigned types.
{
    if ( a < b )  swap2(a, b);
    if ( b==0 )  return a;

    Type r = a % b;
    a = b;
    b = r;
    if ( b==0 )  return a;

    ulong k = 0;
    while ( !((a|b)&1) )  // both even
    {
        k++;
        a >>= 1;
        b >>= 1;
    }

    while ( !(a&1) )  a >>= 1;
    while ( !(b&1) )  b >>= 1;

    while ( 1 )
    {
        if ( a==b )  return  a << k;

        if ( a < b )  swap2(a, b);
        Type t = (a-b) >> 1;  // t>0

        while ( !(t&1) )  t >>= 1;
        a = t;
    }
}
// -------------------------


template <typename Type>
Type binary_sgcd(Type a, Type b)
// Return greatest common divisor of a and b.
// Version for signed types.
{
    if ( a < b )  swap2(a, b);
    if ( b==0 )  return a;

    Type r = a % b;
    a = b;
    b = r;
    if ( b==0 )  return a;

    ulong k = 0;
    while ( !((a|b)&1) )  // both even
    {
        k++;
        a >>= 1;
        b >>= 1;
    }

    while ( !(a&1) )  a >>= 1;
    while ( !(b&1) )  b >>= 1;

    while ( 1 )
    {
        Type t = (a-b) >> 1;
        if ( t==0 )  return  a << k;

        while ( !(t&1) )  t >>= 1;

        if ( t>0 )  a =  t;  // <--= signed
        else        b = -t;
    }
}
// -------------------------

#endif  // !defined HAVE_BINARYGCD_H__
