from __future__ import division, print_function, absolute_import

import sys
from numpy.testing import *
import numpy.linalg as linalg

def random(size):
    return rand(*size)

class TestSolve(TestCase):

    def bench_random(self):
        basic_solve = linalg.solve
        print()
        print('      Solving system of linear equations')
        print('      ==================================')

        print('      |    contiguous     |   non-contiguous ')
        print('----------------------------------------------')
        print(' size |  scipy  | basic   |  scipy  | basic ')

        for size,repeat in [(20,1000),(100,150),(500,2),(1000,1)][:-1]:
            repeat *= 2
            print('%5s' % size, end=' ')
            sys.stdout.flush()

            a = random([size,size])
            # larger diagonal ensures non-singularity:
            for i in range(size): a[i,i] = 10*(.1+a[i,i])
            b = random([size])

            print('| %6.2f ' % measure('solve(a,b)',repeat), end=' ')
            sys.stdout.flush()

            print('| %6.2f ' % measure('basic_solve(a,b)',repeat), end=' ')
            sys.stdout.flush()

            a = a[-1::-1,-1::-1] # turn into a non-contiguous array
            assert_(not a.flags['CONTIGUOUS'])

            print('| %6.2f ' % measure('solve(a,b)',repeat), end=' ')
            sys.stdout.flush()

            print('| %6.2f ' % measure('basic_solve(a,b)',repeat), end=' ')
            sys.stdout.flush()

            print('   (secs for %s calls)' % (repeat))

class TestInv(TestCase):

    def bench_random(self):
        basic_inv = linalg.inv
        print()
        print('           Finding matrix inverse')
        print('      ==================================')
        print('      |    contiguous     |   non-contiguous ')
        print('----------------------------------------------')
        print(' size |  scipy  | basic   |  scipy  | basic')

        for size,repeat in [(20,1000),(100,150),(500,2),(1000,1)][:-1]:
            repeat *= 2
            print('%5s' % size, end=' ')
            sys.stdout.flush()

            a = random([size,size])
            # large diagonal ensures non-singularity:
            for i in range(size): a[i,i] = 10*(.1+a[i,i])

            print('| %6.2f ' % measure('inv(a)',repeat), end=' ')
            sys.stdout.flush()

            print('| %6.2f ' % measure('basic_inv(a)',repeat), end=' ')
            sys.stdout.flush()

            a = a[-1::-1,-1::-1] # turn into a non-contiguous array
            assert_(not a.flags['CONTIGUOUS'])

            print('| %6.2f ' % measure('inv(a)',repeat), end=' ')
            sys.stdout.flush()

            print('| %6.2f ' % measure('basic_inv(a)',repeat), end=' ')
            sys.stdout.flush()

            print('   (secs for %s calls)' % (repeat))


class TestDet(TestCase):

    def bench_random(self):
        basic_det = linalg.det
        print()
        print('           Finding matrix determinant')
        print('      ==================================')
        print('      |    contiguous     |   non-contiguous ')
        print('----------------------------------------------')
        print(' size |  scipy  | basic   |  scipy  | basic ')

        for size,repeat in [(20,1000),(100,150),(500,2),(1000,1)][:-1]:
            repeat *= 2
            print('%5s' % size, end=' ')
            sys.stdout.flush()

            a = random([size,size])

            print('| %6.2f ' % measure('det(a)',repeat), end=' ')
            sys.stdout.flush()

            print('| %6.2f ' % measure('basic_det(a)',repeat), end=' ')
            sys.stdout.flush()

            a = a[-1::-1,-1::-1] # turn into a non-contiguous array
            assert_(not a.flags['CONTIGUOUS'])

            print('| %6.2f ' % measure('det(a)',repeat), end=' ')
            sys.stdout.flush()

            print('| %6.2f ' % measure('basic_det(a)',repeat), end=' ')
            sys.stdout.flush()

            print('   (secs for %s calls)' % (repeat))


if __name__ == "__main__":
    run_module_suite()
