/* **********************************************************************************
 *
 * Copyright (c) Microsoft Corporation. All rights reserved.
 *
 * This source code is subject to terms and conditions of the Shared Source License
 * for IronPython. A copy of the license can be found in the License.html file
 * at the root of this distribution. If you can not locate the Shared Source License
 * for IronPython, please send an email to ironpy@microsoft.com.
 * By using this source code in any fashion, you are agreeing to be bound by
 * the terms of the Shared Source License for IronPython.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * **********************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;

using IronMath;

namespace IronPython.Runtime {
    public static partial class Int64Ops {
        #region Generated Int64Ops

        // *** BEGIN GENERATED CODE ***


        [PythonName("__add__")]
        public static object Add(long x, object other) {
            if (other is int) {
                int y = (int)other;
                try {
                    return Ops.Long2Object(checked(x + y));
                } catch (OverflowException) {
                    return BigInteger.Create(x) + y;
                }
            } else if (other is BigInteger) {
                return BigInteger.Create(x) + (BigInteger)other;
            } else if (other is double) {
                return x + (double)other;
            } else if (other is Complex64) {
                return Complex64.MakeReal(x) + (Complex64)other;
            } else if (other is long) {
                long y = (long)other;
                try {
                    return checked(x + y);
                } catch (OverflowException) {
                    return BigInteger.Create(x) + y;
                }
            } else if (other is float) {
                return x + (float)other;
            }
            return Ops.NotImplemented;
        }


        [PythonName("__sub__")]
        public static object Subtract(long x, object other) {
            if (other is int) {
                int y = (int)other;
                try {
                    return Ops.Long2Object(checked(x - y));
                } catch (OverflowException) {
                    return BigInteger.Create(x) - y;
                }
            } else if (other is BigInteger) {
                return BigInteger.Create(x) - (BigInteger)other;
            } else if (other is double) {
                return x - (double)other;
            } else if (other is Complex64) {
                return Complex64.MakeReal(x) - (Complex64)other;
            } else if (other is long) {
                long y = (long)other;
                try {
                    return checked(x - y);
                } catch (OverflowException) {
                    return BigInteger.Create(x) - y;
                }
            } else if (other is float) {
                return x - (float)other;
            }
            return Ops.NotImplemented;
        }


        [PythonName("__pow__")]
        public static object Power(long x, object other) {
            if (other is int) {
                return Power(x, (int)other);
            } else if (other is long) {
                return Power(x, (long)other);
            } else if (other is double) {
                return FloatOps.Power(x, (double)other);
            } else if (other is float) {
                return FloatOps.Power(x, (float)other);
            }
            return Ops.NotImplemented;
        }


        [PythonName("__mul__")]
        public static object Multiply(long x, object other) {
            if (other is int) {
                int y = (int)other;
                try {
                    return Ops.Long2Object(checked(x * y));
                } catch (OverflowException) {
                    return BigInteger.Create(x) * y;
                }
            } else if (other is BigInteger) {
                return BigInteger.Create(x) * (BigInteger)other;
            } else if (other is double) {
                return x * (double)other;
            } else if (other is Complex64) {
                return Complex64.MakeReal(x) * (Complex64)other;
            } else if (other is long) {
                long y = (long)other;
                try {
                    return checked(x * y);
                } catch (OverflowException) {
                    return BigInteger.Create(x) * y;
                }
            } else if (other is float) {
                return x * (float)other;
            }
            return Ops.NotImplemented;
        }


        [PythonName("__floordiv__")]
        public static object FloorDivide(long x, object other) {
            if (other is int) {
                int y = (int)other;
                try {
                    return Ops.Long2Object(Divide(x, y));
                } catch (OverflowException) {
                    return BigInteger.Create(x) / y;
                }
            } else if (other is BigInteger) {
                return LongOps.Divide(BigInteger.Create(x), (BigInteger)other);
            } else if (other is double) {
                return x / (double)other;
            } else if (other is Complex64) {
                return Complex64.MakeReal(x) / (Complex64)other;
            } else if (other is long) {
                long y = (long)other;
                try {
                    return Divide(x, y);
                } catch (OverflowException) {
                    return BigInteger.Create(x) / y;
                }
            } else if (other is float) {
                return x / (float)other;
            }
            return Ops.NotImplemented;
        }


        [PythonName("__div__")]
        public static object TrueDivide(long x, object other) {
            if (other is int) {
                return TrueDivide(x, (int)other);
            } else if (other is long) {
                return TrueDivide(x, (long)other);
            } else if (other is double) {
                return FloatOps.TrueDivide(x, (double)other);
            } else if (other is float) {
                return FloatOps.TrueDivide(x, (float)other);
            }
            return Ops.NotImplemented;
        }


        [PythonName("__mod__")]
        public static object Mod(long x, object other) {
            if (other is int) {
                int y = (int)other;
                try {
                    return Ops.Long2Object(Mod(x, y));
                } catch (OverflowException) {
                    return BigInteger.Create(x) % y;
                }
            } else if (other is BigInteger) {
                return LongOps.Mod(BigInteger.Create(x), (BigInteger)other);
            } else if (other is double) {
                return x % (double)other;
            } else if (other is Complex64) {
                return Complex64.MakeReal(x) % (Complex64)other;
            } else if (other is long) {
                long y = (long)other;
                try {
                    return Mod(x, y);
                } catch (OverflowException) {
                    return BigInteger.Create(x) % y;
                }
            } else if (other is float) {
                return x % (float)other;
            }
            return Ops.NotImplemented;
        }


        [PythonName("__and__")]
        public static object BitwiseAnd(long x, object other) {
            if (other is int) {
                long y = (long)(int)other;
                return Ops.Long2Object(x & y);
            } else if (other is long) {
                return x & (long)other;
            } else if (other is BigInteger) {
                return BigInteger.Create(x) & (BigInteger)other;
            }
            return Ops.NotImplemented;
        }


        [PythonName("__or__")]
        public static object BitwiseOr(long x, object other) {
            if (other is int) {
                long y = (long)(int)other;
                return Ops.Long2Object(x | y);
            } else if (other is long) {
                return x | (long)other;
            } else if (other is BigInteger) {
                return BigInteger.Create(x) | (BigInteger)other;
            }
            return Ops.NotImplemented;
        }


        [PythonName("__xor__")]
        public static object Xor(long x, object other) {
            if (other is int) {
                long y = (long)(int)other;
                return Ops.Long2Object(x ^ y);
            } else if (other is long) {
                return x ^ (long)other;
            } else if (other is BigInteger) {
                return BigInteger.Create(x) ^ (BigInteger)other;
            }
            return Ops.NotImplemented;
        }


        // *** END GENERATED CODE ***

        #endregion

    }
}
