import commands, time

directory="./Examples/"

def run_mul(n, ctr=11):
    n = int(n)
    l = []
    print "mul n=%5d:"%(n),
    for i in xrange(ctr):
        A = random_matrix(GF(2), n, n)
        B = random_matrix(GF(2), n, n)
        t = cputime()
        C = A*B
        l.append(cputime(t))
        print ".",
        sys.stdout.flush()
    _min, _avg, _med, _max = min(l), sum(l)/ctr, sorted(l)[ctr/2+1], max(l)
    print " % 8.3f % 8.3f % 8.3f % 8.3f"%(_min, _avg, _med, _max)
    return (('mul',n), _med)

def run_elim(m, n, algorithm, ctr=11):
    m,n = int(m), int(n)
    l = []
    print "elim m=%5d n=%5d algorithm='%s:'"%(m,n,algorithm),
    for i in xrange(ctr):
        A = random_matrix(GF(2), m, n)
        t = cputime()
        E = A.echelon_form(algorithm=algorithm)
        l.append(cputime(t))
        print ".",
        sys.stdout.flush()
    _min, _avg, _med, _max = min(l), sum(l)/ctr, sorted(l)[ctr/2+1], max(l)
    print " % 8.3f % 8.3f % 8.3f % 8.3f"%(_min, _avg, _med, _max)
    return (('elim',m,n,algorithm),_med)

def run_elim_sparse(m, n, density, algorithm, ctr=11):
    m,n = int(m), int(n)
    density = float(density)
    l = []
    print "elim m=%5d n=%5d density=%6.4f algorithm='%s:'"%(m,n,density,algorithm),
    for i in xrange(ctr):
        A = random_matrix(GF(2), m, n, density=density)
        t = cputime()
        E = A.echelon_form(algorithm=algorithm)
        l.append(cputime(t))
        print ".",
        sys.stdout.flush()
    _min, _avg, _med, _max = min(l), sum(l)/ctr, sorted(l)[ctr/2+1], max(l)
    print " % 8.3f % 8.3f % 8.3f % 8.3f"%(_min, _avg, _med, _max)
    return (('elim-sparse',m,n,density,algorithm),_med)

def run_elim_name(name, algorithm):
    A = sage.matrix.matrix_mod2_dense.from_png(directory + name + ".png")
    t = cputime()
    E = A.echelon_form(algorithm=algorithm)
    t = cputime(t)
    print "elim name='%s' algorithm='%s:' . %7.3f"%(name,algorithm,t)
    return (('elim',name,algorithm),t)

def get_timings(ctr=3, big=False):
    ctr = int(ctr)
    d = {}
    cpu = hash(commands.getoutput("cat /proc/cpuinfo"))
    date = time.localtime()

    try:
        x,y = run_elim_name('hfe25_5', 'm4ri'); d[x] = y
    except IOError:
        pass
    try:
        x,y = run_elim_name('hfe30_5', 'm4ri'); d[x] = y
    except IOError:
        pass
    if big:
        try:
            x,y = run_elim_name('hfe35_5', 'm4ri'); d[x] = y
        except IOError:
            pass

    try:
        x,y = run_elim_name('hfe25_5', 'pluq'); d[x] = y
    except (IOError, ValueError):
        pass

    try:
        x,y = run_elim_name('hfe30_5', 'pluq'); d[x] = y
    except (IOError, ValueError):
        pass
    if big:
        try:
            x,y = run_elim_name('hfe35_5', 'pluq'); d[x] = y
        except (IOError, ValueError):
            pass

    if big:
        try: 
            x,y = run_elim_name('mutant_matrix', 'm4ri'); d[x] = y
        except IOError:
            pass
        try:
            x,y = run_elim_name('mutant_matrix', 'pluq'); d[x] = y
        except (IOError, ValueError):
            pass
    
    print ""

    x,y = run_mul(10**4, ctr); d[x] = y
    x,y = run_mul(2**14, ctr); d[x] = y
    x,y = run_mul(2*10**4, ctr); d[x] = y
    if big:
        x,y = run_mul(3.2*10**4,ctr); d[x] = y

    print ""

    x,y = run_elim(10**4, 10**4, 'm4ri', ctr); d[x] = y
    x,y = run_elim(2**14, 2**14, 'm4ri', ctr); d[x] = y
    x,y = run_elim(2*10**4, 2*10**4, 'm4ri', ctr); d[x] = y
    if big:
        x,y = run_elim(3.2*10**4, 3.2*10**4, 'm4ri', ctr); d[x] = y

    try:
        x,y = run_elim(10**4, 10**4, 'pluq', ctr); d[x] =y 
        x,y = run_elim(2**14, 2**14, 'pluq', ctr); d[x] = y
        x,y = run_elim(2*10**4, 2*10**4, 'pluq', ctr); d[x] = y
        if big:
            x,y = run_elim(3.2*10**4, 3.2*10**4, 'pluq', ctr); d[x] = y
    except ValueError:
        pass

    print ""

    x,y = run_elim_sparse(10**4, 10**4,  2.0/10**4, 'm4ri', ctr); d[x] = y
    x,y = run_elim_sparse(10**4, 10**4,  4.0/10**4, 'm4ri', ctr); d[x] = y
    x,y = run_elim_sparse(10**4, 10**4,  6.0/10**4, 'm4ri', ctr); d[x] = y
    x,y = run_elim_sparse(10**4, 10**4,  8.0/10**4, 'm4ri', ctr); d[x] = y
    x,y = run_elim_sparse(10**4, 10**4, 10.0/10**4, 'm4ri', ctr); d[x] = y

    x,y = run_elim_sparse(10**4, 10**4,  2.0/10**4, 'pluq', ctr); d[x] = y
    x,y = run_elim_sparse(10**4, 10**4,  4.0/10**4, 'pluq', ctr); d[x] = y
    x,y = run_elim_sparse(10**4, 10**4,  6.0/10**4, 'pluq', ctr); d[x] = y
    x,y = run_elim_sparse(10**4, 10**4,  8.0/10**4, 'pluq', ctr); d[x] = y
    x,y = run_elim_sparse(10**4, 10**4, 10.0/10**4, 'pluq', ctr); d[x] = y

    print ""

    x,y = run_elim(10**4, 2*10**4, 'm4ri', ctr); d[x] = y
    x,y = run_elim(2**14, 2*2**14, 'm4ri', ctr); d[x] = y
    if big:
        x,y = run_elim(2*10**4, 2*2*10**4, 'm4ri', ctr); d[x] = y
        x,y = run_elim(3.2*10**4, 2*3.2*10**4, 'm4ri', ctr); d[x] = y

    try:
        x,y = run_elim(10**4, 2*10**4, 'pluq', ctr); d[x] = y
        x,y = run_elim(2**14, 2*2**14, 'pluq', ctr); d[x] = y
        if big:
            x,y = run_elim(2*10**4, 2*2*10**4, 'pluq', ctr); d[x] = y
            x,y = run_elim(3.2*10**4, 2*3.2*10**4, 'pluq', ctr); d[x] = y
    except ValueError:
        pass

    return (cpu, date, d)

def get_and_save_timings(fn='timings.sobj', **kwds):
    r = get_timings(**kwds)
    save(r, fn)
    return r

def compare_timings(fn, **kwds):
    cpu0, date0, data0 = load(fn)
    cpu1, date1, data1 = get_timings(**kwds)
    date0 = "%04d-%02d-%02d %02d:%02d"%(date0[0],date0[1],date0[2],date0[3],date0[4])
    date1 = "%04d-%02d-%02d %02d:%02d"%(date1[0],date1[1],date1[2],date1[3],date1[4])

    print "\nComparing %s and %s\n"%(date1,date0)
    for k in sorted(data1):
        if k in data0:
            print "%40s: %7.3f / %7.3f = %5.3f"%(k, data1[k], data0[k], data1[k]/data0[k])
    
    return (cpu1, date1, data1)
