/*
 * Copyright (c) 2013, Regents of the University of California
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package edu.uci.python.test.grammar;

import static edu.uci.python.test.PythonTests.*;

import org.junit.*;

public class BinaryArithTests {

    @Test
    public void binaryOps() {
        String source = "a = 1 + 2\n" + //
                        "b = 4 - 2\n" + //
                        "c = 6 * 2\n" + //
                        "d = 7 / 2\n" + //
                        "e = 7 // 2\n" + //
                        "print(a,b,c,d,e)\n";
        assertPrints("3 2 12 3.5 3\n", source);
    }

    @Test
    public void bigIntegerDiv() {
        String source = "print(22222222222222222222 / 2)\n";
        assertPrints("1.111111111111111e+19\n", source);
    }

    @Test
    public void simpleIntegerDiv() {
        String source = "print(7 / 2)\n";
        assertPrints("3.5\n", source);
    }

    @Test
    public void additionAndMultiply() {
        String source = "print(345606 + 364 * 2)\n";
        assertPrints("346334\n", source);
    }

    @Test
    public void shouldBeInteger() {
        String source = "print(64 * 64 / (16 * 16))\n";
        assertPrints("16.0\n", source);
    }

    @Test
    public void intOverflow() {
        String source = "print((30020 + 2**31) % 2**32 - 2**31)\n";
        assertPrints("30020\n", source);
    }

    @Test
    public void intOverflowPow() {
        String source = "x = 2**31 + 3; print(x)\n";
        assertPrints("2147483651\n", source);
    }

    @Test
    public void divisionAndMinus() {
        String source = "print(1101010101 / 356 - 2002)\n";
        assertPrints("3090723.0028089886\n", source);
    }

    @Test
    public void minusAndMultiply() {
        String source = "print(42 - 99999 * 543858438584385)\n";
        assertPrints("-54385299999999915573\n", source);
    }

    @Test
    public void divisonAndMultiply() {
        String source = "print(1 / 356 * 2.0)\n";
        assertPrints("0.0056179775280898875\n", source);
    }

    @Test
    public void trueDivisionWithDouble() {
        String source = "print(3 // 5.0)\n";
        assertPrints("0.0\n", source);
    }

    @Test
    public void complexBinaryArith2() {
        String source = "a = 46372573068954628579 / 432\n" + //
                        "b = 46372573068954628579 / 43.2\n" + //
                        "c = (3.56 - 5278948673290672067) // 6427069\n" + //
                        "d = 2 ** 4\n" + //
                        "e = 2.5 ** 3.0\n" + //
                        "print(a,b,c,d,e)\n";
        assertPrints("1.07343919141098672e+17 1.07343919141098675e+18 -8.21361754992e+11 16 15.625\n", source);
    }

    @Test
    public void modulo() {
        assertPrints("4\n", "print(14 % 5)");
        assertPrints("20\n", "print(54528840284285205820 % 52)");
        assertPrints("2.7440432148750915e-09\n", "print(43253252 % 0.7)");
    }

    @Test
    public void int64() {
        String source = "BB_ALL = 0b1111111111111111111111111111111111111111111111111111111111111111\n" + //
                        "print(BB_ALL)\n";
        assertPrints("18446744073709551615\n", source);
    }

    @Test
    public void NonePlusInt() {
        String source = "a = None\n" + //
                        "a += 1\n";
        assertError("TypeError: unsupported operand type(s) for +: None + 1\n", source);
    }

}
