#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>

// hard parameters
#define L 150
#define MULTISPIN unsigned int
#define MULTISIZE 32
// #define MULTISPIN unsigned long int
// #define MULTISIZE 64

#define STEPS_REPEAT 3

const int AREA = L*L;
const int NTOT = (L-2)*(L-2);


//external parameters

struct parameters {
    float t;
    float t_start;
    float j;
    int steps_repeat;
    int t_max_sim;
    int t_measure_wait;
    int t_measure_interval;
    int seed;
};



// average tracker struct
struct avg_tr {
    double sum;
    double sum_squares;
    int n;
};
static inline struct avg_tr new_avg_tr(int locn) {
    struct avg_tr a = { .sum = 0, .sum_squares = 0, .n = locn};
    return a;
}
// if the numbers overflow, then it would be necessary to divide by N before summing
// however it's faster the other way
static inline void update_avg(struct avg_tr * tr_p, double newval) {
    tr_p->sum +=  newval;
    tr_p->sum_squares += (newval*newval);
}
static inline double average( struct avg_tr tr) {
    return (tr.sum)/((double) tr.n) ;
}
static inline double stdev( struct avg_tr tr) {
    return sqrt(  ( tr.sum_squares)/((double) tr.n)  -  pow(( (tr.sum)/((double) tr.n) ),2)  );
}
// static inline double variance( struct avg_tr tr) {
//     return (  ( tr.sum_squares)/((double) tr.n)  -  pow(( (tr.sum)/((double) tr.n) ),2)  );
// }

//multispin averages, hard-coded to track a number MULTISPIN * STEPS_REPEAT of values
struct multiavg_tr {
    double sum[MULTISIZE * STEPS_REPEAT];
    double sum_squares[MULTISIZE * STEPS_REPEAT];
    int n; // number of terms in the avg
};
// localn is not multisize*steps_repeat, it's the number of terms that will contribute to each avg ...
struct multiavg_tr new_multiavg_tr(int localn) {
    struct multiavg_tr a;
    for(int k=0; k<MULTISIZE * STEPS_REPEAT; k++ ) {
        a.sum[k] = 0;
        a.sum_squares[k] = 0;
    }
    a.n = localn;
    return a;
}
// must be 0 =< k < MULTISIZE * STEPS_REPEAT
static inline void update_multiavg(struct multiavg_tr * tr_p, double newval, int k) {
    tr_p->sum[k] +=  newval;
    tr_p->sum_squares[k] += (newval*newval);
}
static inline double multiaverage( struct multiavg_tr tr, int k) {
    return (tr.sum[k])/((double) tr.n) ;
}
static inline double multistdev( struct multiavg_tr tr, int k) {
    return sqrt(  ( tr.sum_squares[k])/((double) tr.n)  -  pow(( (tr.sum[k])/((double) tr.n) ),2)  );
}
// static inline double multivariance( struct multiavg_tr tr, int k) {
//     return (  ( tr.sum_squares[k])/((double) tr.n)  -  pow(( (tr.sum[k])/((double) tr.n) ),2)  );
// }




double unitrand(){
    return (double)rand() / (double)RAND_MAX;
}

// index has to be less that MULTISIZE
static inline void set_spin_1 (MULTISPIN * multi, int index) {
    *multi |= 1 << index;
}
static inline void set_spin_0 (MULTISPIN * multi, int index) {
    *multi &= ~(1 << index);
}
static inline MULTISPIN read_spin(MULTISPIN multi, int index) {
    return ((multi >> index) & 1);
}

// each bit exp8 and exp8 describes the Metropolis RNG result for that bit,
// specifying if the random r is bigger or smaller than the relevant values e^(4J/kT) and e^(8J/kT) (passed from outside)
static inline MULTISPIN generate_exp4_mask(double exp4, double exp8, double random_number) {
    MULTISPIN res;
    for(int k=0; k<MULTISIZE; k++) {
        if( exp4 > random_number && random_number > exp8) { // this is taken from the article and works. the version below might not but simplifies some things
        // if( exp4 > random_number) {
            set_spin_1(&res, k);
        } else {
            set_spin_0(&res, k);
        }
    }
    return res;
}
static inline MULTISPIN generate_exp8_mask(double exp8, double random_number) {
    MULTISPIN res;
    for(int k=0; k<MULTISIZE; k++) {
        if( random_number < exp8 ) {
            set_spin_1(&res, k);
        } else {
            set_spin_0(&res, k);
        }
    }
    return res;
}

MULTISPIN init_random_multispin() {
    return (MULTISPIN) rand(); // just spam random bits
}
void init_random_grid(MULTISPIN grid[L*L]) {
    for(int x = 0; x<L; x++) {
        for(int y = 0; y<L; y++) {
            grid[x+y*L] = init_random_multispin();
        }
    }
}


MULTISPIN init_t0_multispin() {
    return (MULTISPIN) 0; // should be all zeros for all sensible multispin types
}
void init_t0_grid(MULTISPIN grid[L*L]) {
    for(int x = 0; x<L; x++) {
        for(int y = 0; y<L; y++) {
            grid[x+y*L] = init_t0_multispin();
        }
    }
}

// static inline void flip(MULTISPIN grid[L*L], int x, int y) {
//     grid[x+y*L] = ~grid[x+y*L];
// }

// can segfault 
static inline MULTISPIN grid_step(MULTISPIN grid[L*L], int x, int y, int xstep, int ystep) {
    return grid[(x+xstep)  + (y+ystep)*L];
}


// segfault if applied to an edge spin, must be called only on the inner L-1 grid
void update_multispin(MULTISPIN grid[L*L], int x, int y, double exp4, double exp8 ) {

    MULTISPIN s0 = grid[x+y*L];
    
    double ur = unitrand(); 
    MULTISPIN exp4_mask = generate_exp4_mask(exp4, exp8, ur); // here
    MULTISPIN exp8_mask = generate_exp8_mask(exp8, ur);

    // "energy variables" indicating whether s0 is equal or opposite to each of its 4 neighbours 
    MULTISPIN i1 = s0 ^ grid_step(grid, x, y, 1, 0);
    MULTISPIN i2 = s0 ^ grid_step(grid, x, y, -1, 0);
    MULTISPIN i3 = s0 ^ grid_step(grid, x, y, 0, 1);
    MULTISPIN i4 = s0 ^ grid_step(grid, x, y, 0, -1);
    
    // bit sums with carry over between the i variables
    MULTISPIN j1 = i1 & i2;
    MULTISPIN j2 = i1 ^ i2;
    MULTISPIN j3 = i3 & i4;
    MULTISPIN j4 = i3 ^ i4;

    // logic for deciding whether to flip s0 or not
    MULTISPIN flip_mask = ( ((j1 | j3) | (~(j1^j3) & (j2&j4))  )  |   ((j2 | j4) & exp4_mask  )   |   exp8_mask );

    grid[x+y*L] = grid[x+y*L] ^ flip_mask;

    // explanation:
    // spins | i1234 | deltaE | j1 j2  j3 j4 |
    //   1   |   1   |        |              |    
    //  101  |  1 1  |   -8   |  1 0    1 0  |                   
    //   1   |   1   |        |              |
    //                                                         
    //   0   |   0   |        |              |    
    //  101  |  1 1  |   -4   |  0 1    1 0  |         (j1 | j3)          
    //   1   |   1   |        |              |
    //                                                         
    //   0   |   0   |        |  0 0    1 0  |    
    //  001  |  0 1  |    0   |      or      |-------------------------                  
    //   1   |   1   |        |  0 1    0 1  |      ~(j1^j3) & (j2&j4))
    //------------------------------------------------------------------
    //                                                        
    //   0   |   0   |        |              |    
    //  000  |  0 0  |    +4  |              |       (j2 | j4) & exp4      
    //   1   |   1   |        |              |
    //------------------------------------------------------------------ 
    //                                                        
    //   0   |   0   |        |              |    
    //  000  |  0 0  |    +8  |  0 0    0 0  |           exp8       
    //   0   |   0   |        |              |

    // the first 2 cases are detected by (j1 | j3) and lead to the spin flip regardless of the RNG roll.
    // the deltaH = 0 case can result in two different forms for the j's depending on ho the spins are paired. 
    //   the first of these is correctly picked up by (j1 | j3), while the second needs its own expression ~(j1^j3) & (j2&j4))
    // in the 4th case, detected by (j2 | j4), the spin is flipped only if the RNG roll is lucky enough (exp4 = 1)
    // if we still haven't flipped, we get to the last case. here the spin is flipped only if the RNG roll gives the luckiest result (exp8 = 1).
    
}

// checkerboard patterns
void update_grid_white(MULTISPIN grid[L*L], double exp4, double exp8 ) {
    for(int x = 1; x<L-1; x+=1) {
        for(int y = (1 + x%2) ; y<L-1; y+=2) {
            update_multispin(grid, x, y, exp4, exp8);
        }
    }
}
void update_grid_black(MULTISPIN grid[L*L], double exp4, double exp8 ) {
    for(int x = 1; x<L-1; x+=1) {
        for(int y = (1 + (x+1)%2) ; y<L-1; y+=2) {
            update_multispin(grid, x, y, exp4, exp8);
        }
    }
}

// non GPU function
void multidump_first(MULTISPIN grid[L*L]) {
    // printf("first bit grid (out of %i):\n", MULTISIZE);
    for(int x = 0; x<L; x++) {
        for(int y = 0; y<L; y++) {
            
            if(( grid[x+y*L] & 1 ) == 0) printf(" ");
            else printf("█");

        }
        printf("\n");
    }
    printf("\n");
}

// non GPU function
void multidump_a_few(MULTISPIN grid[L*L]) {
    for(int k=0; k<5; k++) {
        printf("grid on bit %i (out of %i):\n", k+1, MULTISIZE);
        for(int x = 0; x<L; x++) {
            for(int y = 0; y<L; y++) {
                
                if(( grid[x+y*L] & (1 << k) ) == 0) printf(" ");
                else printf("█");

            }
            printf("\n");
        }
        printf("\n");
    }
}

// non GPU
double measure_1bit_magnetization(MULTISPIN grid[L*L], int multi_index) {
    double lmagn = 0;
    for(int x = 1; x<L-1; x++) {
        for(int y = 1; y<L-1; y++) {
            double bit = (double) read_spin(grid[x+y*L], multi_index); 
            lmagn = lmagn + ((bit*2.) -1.);
        }
    }

    return (((double) lmagn ) / (double) NTOT) ;
}

// as usual, the number of independent measures is hardcoded to MULTISIZE * STEPS_REPEAT.
// this function measures a single multispin, updating a chunk of the tracker. (for example the first half if rep_steps is 2)
void update_magnetization_tracker( struct multiavg_tr * tr_p, MULTISPIN grid[L*L], int block_count) {
    for( int k=0; k < MULTISIZE; k++) {
        double mag = measure_1bit_magnetization(grid, k);
        update_multiavg(tr_p, mag, k + MULTISIZE*block_count );
    }
}

// static inline void update_multiavg(struct multiavg_tr * tr_p, double newval, int k) {
//     tr_p->sum[k] +=  newval;
//     tr_p->sum_squares[k] += (newval*newval);
// }


int main() {
    // read params

    FILE *param_f = fopen("params.txt", "r");
    struct parameters par;

    fscanf(param_f, "temperature %f\ntemperature_start %f\ncoupling %f\nsimulation_t_max %i\nthermalization_time %i\ntime_between_measurements %i\nbase_random_seed %i\n", 
                    &(par.t),     &(par.t_start),     &(par.j),    &(par.t_max_sim),   &(par.t_measure_wait),   &(par.t_measure_interval),       &(par.seed));
    printf("%f\n", par.t);
    printf("%f\n", par.t_start);
    printf("%f\n", par.j);
    printf("%i\n", par.t_max_sim);
    printf("%i\n", par.t_measure_wait);
    printf("%i\n", par.t_measure_interval);
    printf("%i\n", par.seed);
    fclose(param_f);


    srand(par.seed);
    MULTISPIN startgrid[L*L];
    init_t0_grid(startgrid);



    const double EXP4 = exp( -(4.*par.j) / par.t);
    const double EXP8 = exp( -(8.*par.j) / par.t);

    // measure cycle
    FILE *resf = fopen("results.txt", "w");
    fprintf(resf, "# cpu2\n");
    fprintf(resf, "# hard-coded parameters:\n# linear_size: %i\n# spin_coding_size: %i\n", L, MULTISIZE);
    fprintf(resf, "# parameters:\n# temperature: %f\n#temp_start: %f\n# coupling: %f\n# repetitions: %i\n", par.t, par.t_start, par.j, STEPS_REPEAT);
    fprintf(resf, "# simulation_t_max: %i\n# thermalization_time: %i\n# time_between_measurements: %i\n# base_random_seed: %i\n",  par.t_max_sim, par.t_measure_wait, par.t_measure_interval, par.seed);
    fprintf(resf, "# extra:\n# area: %i\n# active_spins_excluding_boundaries:%i\n# total_independent_sims: %i\n", AREA, NTOT, MULTISIZE*STEPS_REPEAT);
    
    MULTISPIN grid[L*L];
    double n_measures_per_sim = (double) ((par.t_max_sim - par.t_measure_wait)/par.t_measure_interval);

    //OUTER REP LOOP  
    struct multiavg_tr single_run_avgs = new_multiavg_tr(n_measures_per_sim);

    for( int krep=0; krep< STEPS_REPEAT; krep++) {
        srand(par.seed + krep);
        memcpy(grid, startgrid, L*L*sizeof(MULTISPIN) );

        // INNER SIM LOOPS
        printf("# simulation %i\n", krep+1);
        printf("#    waiting thermalization for the first %i sim steps.\n", par.t_measure_wait);
        int ksim=0;
        for( ; ksim<par.t_measure_wait; ksim++) {
            update_grid_black(grid, EXP4, EXP8);
            update_grid_white(grid, EXP4, EXP8);
        }
        printf("#    finished thermalization. running %i more simulation steps and performing %f measures.\n",(par.t_max_sim - par.t_measure_wait), n_measures_per_sim);

        for( ; ksim<par.t_max_sim; ksim++) {
            update_grid_black(grid, EXP4, EXP8);
            update_grid_white(grid, EXP4, EXP8);
            
            if( ksim % par.t_measure_interval == 0) {
                update_magnetization_tracker(&single_run_avgs, grid, krep);
            }
        }
        // END INNER SIM LOOPS        
        printf("# end simulation %i\n", krep+1);
    }
    // END OUTER REPETITION LOOP

    struct avg_tr avg_of_blocks = new_avg_tr( MULTISIZE * STEPS_REPEAT );

    for(int k=0; k < MULTISIZE * STEPS_REPEAT; k++) {
        double lres = multiaverage(single_run_avgs, k);
        double lstdev = multistdev(single_run_avgs, k);

        fprintf(resf, "# average of simulation %i\n: %f +- %f\n", k+1, lres, lstdev);
        update_avg(&avg_of_blocks, lres);
    }
    fprintf(resf, "# overall average \n: %f +- %f\n", average(avg_of_blocks), stdev(avg_of_blocks));

    multidump_a_few(grid);





    return 0;
}


	.file	"tmpxft_003ab18e_00000000-6_main.cudafe1.cpp"
	.text
#APP

#NO_APP
	.type	_ZL26__cudaUnregisterBinaryUtilv, @function
_ZL26__cudaUnregisterBinaryUtilv:
.LFB2056:
	.cfi_startproc
	endbr64
	movq	_ZL20__cudaFatCubinHandle(%rip), %rdi
	jmp	__cudaUnregisterFatBinary@PLT
	.cfi_endproc
.LFE2056:
	.size	_ZL26__cudaUnregisterBinaryUtilv, .-_ZL26__cudaUnregisterBinaryUtilv
	.globl	_Z15new_multiavg_tri
	.type	_Z15new_multiavg_tri, @function
_Z15new_multiavg_tri:
.LFB2031:
	.cfi_startproc
	endbr64
	movq	%rdi, %rdx
	xorl	%eax, %eax
	movl	$384, %ecx
	rep stosl
	movl	%esi, 1536(%rdx)
	movq	%rdx, %rax
	ret
	.cfi_endproc
.LFE2031:
	.size	_Z15new_multiavg_tri, .-_Z15new_multiavg_tri
	.globl	_Z8unitrandv
	.type	_Z8unitrandv, @function
_Z8unitrandv:
.LFB2035:
	.cfi_startproc
	endbr64
	pushq	%rax
	.cfi_def_cfa_offset 16
	call	rand@PLT
	cvtsi2sdl	%eax, %xmm0
	divsd	.LC0(%rip), %xmm0
	popq	%rdx
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2035:
	.size	_Z8unitrandv, .-_Z8unitrandv
	.globl	_Z21init_random_multispinv
	.type	_Z21init_random_multispinv, @function
_Z21init_random_multispinv:
.LFB2041:
	.cfi_startproc
	endbr64
	jmp	rand@PLT
	.cfi_endproc
.LFE2041:
	.size	_Z21init_random_multispinv, .-_Z21init_random_multispinv
	.globl	_Z16init_random_gridPj
	.type	_Z16init_random_gridPj, @function
_Z16init_random_gridPj:
.LFB2042:
	.cfi_startproc
	endbr64
	pushq	%r13
	.cfi_def_cfa_offset 16
	.cfi_offset 13, -16
	movq	%rdi, %r13
	pushq	%r12
	.cfi_def_cfa_offset 24
	.cfi_offset 12, -24
	pushq	%rbp
	.cfi_def_cfa_offset 32
	.cfi_offset 6, -32
	pushq	%rbx
	.cfi_def_cfa_offset 40
	.cfi_offset 3, -40
	xorl	%ebx, %ebx
	pushq	%rdx
	.cfi_def_cfa_offset 48
.L7:
	leaq	0(%r13,%rbx,4), %r12
	movl	$150, %ebp
.L8:
	call	rand@PLT
	addq	$600, %r12
	movl	%eax, -600(%r12)
	decl	%ebp
	jne	.L8
	incq	%rbx
	cmpq	$150, %rbx
	jne	.L7
	popq	%rax
	.cfi_def_cfa_offset 40
	popq	%rbx
	.cfi_def_cfa_offset 32
	popq	%rbp
	.cfi_def_cfa_offset 24
	popq	%r12
	.cfi_def_cfa_offset 16
	popq	%r13
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2042:
	.size	_Z16init_random_gridPj, .-_Z16init_random_gridPj
	.globl	_Z17init_t0_multispinv
	.type	_Z17init_t0_multispinv, @function
_Z17init_t0_multispinv:
.LFB2043:
	.cfi_startproc
	endbr64
	xorl	%eax, %eax
	ret
	.cfi_endproc
.LFE2043:
	.size	_Z17init_t0_multispinv, .-_Z17init_t0_multispinv
	.globl	_Z12init_t0_gridPj
	.type	_Z12init_t0_gridPj, @function
_Z12init_t0_gridPj:
.LFB2044:
	.cfi_startproc
	endbr64
	xorl	%ecx, %ecx
.L15:
	movq	%rdi, %rdx
	movl	$150, %eax
.L16:
	xorl	%esi, %esi
	addq	$600, %rdx
	movl	%esi, -600(%rdx)
	decl	%eax
	jne	.L16
	incl	%ecx
	addq	$4, %rdi
	cmpl	$150, %ecx
	jne	.L15
	ret
	.cfi_endproc
.LFE2044:
	.size	_Z12init_t0_gridPj, .-_Z12init_t0_gridPj
	.globl	_Z16update_multispinPjiidd
	.type	_Z16update_multispinPjiidd, @function
_Z16update_multispinPjiidd:
.LFB2046:
	.cfi_startproc
	endbr64
	pushq	%r15
	.cfi_def_cfa_offset 16
	.cfi_offset 15, -16
	pushq	%r14
	.cfi_def_cfa_offset 24
	.cfi_offset 14, -24
	pushq	%r13
	.cfi_def_cfa_offset 32
	.cfi_offset 13, -32
	pushq	%r12
	.cfi_def_cfa_offset 40
	.cfi_offset 12, -40
	imull	$150, %edx, %r12d
	pushq	%rbp
	.cfi_def_cfa_offset 48
	.cfi_offset 6, -48
	movl	%esi, %ebp
	pushq	%rbx
	.cfi_def_cfa_offset 56
	.cfi_offset 3, -56
	movq	%rdi, %rbx
	leal	(%r12,%rsi), %eax
	cltq
	leaq	(%rdi,%rax,4), %r15
	subq	$40, %rsp
	.cfi_def_cfa_offset 96
	movl	(%r15), %eax
	movsd	%xmm1, 16(%rsp)
	movsd	%xmm0, 24(%rsp)
	movl	%eax, 12(%rsp)
	call	_Z8unitrandv
	movl	12(%rsp), %eax
	xorl	%ecx, %ecx
	movl	$1, %esi
	movsd	24(%rsp), %xmm2
	movsd	16(%rsp), %xmm1
.L24:
	movl	%esi, %edx
	sall	%cl, %edx
	comisd	%xmm0, %xmm2
	jbe	.L20
	comisd	%xmm1, %xmm0
	jbe	.L20
	orl	%edx, %r14d
	jmp	.L23
.L20:
	notl	%edx
	andl	%edx, %r14d
.L23:
	incl	%ecx
	cmpl	$32, %ecx
	jne	.L24
	xorl	%ecx, %ecx
	movl	$1, %esi
.L28:
	movl	%esi, %edx
	sall	%cl, %edx
	comisd	%xmm0, %xmm1
	jbe	.L34
	orl	%edx, %r13d
	jmp	.L27
.L34:
	notl	%edx
	andl	%edx, %r13d
.L27:
	incl	%ecx
	cmpl	$32, %ecx
	jne	.L28
	leal	1(%r12,%rbp), %edx
	leal	150(%r12,%rbp), %ecx
	movl	%eax, %r9d
	movslq	%edx, %rdx
	movslq	%ecx, %rcx
	movl	(%rbx,%rdx,4), %edi
	leal	-1(%r12,%rbp), %edx
	movl	(%rbx,%rcx,4), %r8d
	leal	-150(%r12,%rbp), %ecx
	movslq	%edx, %rdx
	movslq	%ecx, %rcx
	movl	(%rbx,%rdx,4), %edx
	movl	(%rbx,%rcx,4), %esi
	movl	%eax, %ecx
	xorl	%edi, %ecx
	xorl	%edx, %r9d
	xorl	%edi, %edx
	movl	%eax, %edi
	xorl	%esi, %eax
	andl	%r9d, %ecx
	xorl	%r8d, %edi
	xorl	%r8d, %esi
	movl	%edx, %r8d
	andl	%eax, %edi
	movl	%ecx, %eax
	andl	%esi, %r8d
	orl	%esi, %edx
	xorl	%edi, %eax
	orl	%edi, %ecx
	andl	%r14d, %edx
	notl	%eax
	andl	%r8d, %eax
	orl	%ecx, %eax
	orl	%edx, %eax
	orl	%r13d, %eax
	xorl	%eax, (%r15)
	addq	$40, %rsp
	.cfi_def_cfa_offset 56
	popq	%rbx
	.cfi_def_cfa_offset 48
	popq	%rbp
	.cfi_def_cfa_offset 40
	popq	%r12
	.cfi_def_cfa_offset 32
	popq	%r13
	.cfi_def_cfa_offset 24
	popq	%r14
	.cfi_def_cfa_offset 16
	popq	%r15
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2046:
	.size	_Z16update_multispinPjiidd, .-_Z16update_multispinPjiidd
	.globl	_Z17update_grid_whitePjdd
	.type	_Z17update_grid_whitePjdd, @function
_Z17update_grid_whitePjdd:
.LFB2047:
	.cfi_startproc
	endbr64
	pushq	%r14
	.cfi_def_cfa_offset 16
	.cfi_offset 14, -16
	movq	%xmm0, %r14
	pushq	%r12
	.cfi_def_cfa_offset 24
	.cfi_offset 12, -24
	movq	%rdi, %r12
	pushq	%rbp
	.cfi_def_cfa_offset 32
	.cfi_offset 6, -32
	movl	$1, %ebp
	pushq	%rbx
	.cfi_def_cfa_offset 40
	.cfi_offset 3, -40
	subq	$24, %rsp
	.cfi_def_cfa_offset 64
.L38:
	movl	%ebp, %ebx
	andl	$1, %ebx
	incl	%ebx
.L37:
	movl	%ebx, %edx
	movq	%r14, %xmm0
	movl	%ebp, %esi
	movq	%r12, %rdi
	addl	$2, %ebx
	movsd	%xmm1, 8(%rsp)
	call	_Z16update_multispinPjiidd
	cmpl	$148, %ebx
	movsd	8(%rsp), %xmm1
	jle	.L37
	incl	%ebp
	cmpl	$149, %ebp
	jne	.L38
	addq	$24, %rsp
	.cfi_def_cfa_offset 40
	popq	%rbx
	.cfi_def_cfa_offset 32
	popq	%rbp
	.cfi_def_cfa_offset 24
	popq	%r12
	.cfi_def_cfa_offset 16
	popq	%r14
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2047:
	.size	_Z17update_grid_whitePjdd, .-_Z17update_grid_whitePjdd
	.globl	_Z17update_grid_blackPjdd
	.type	_Z17update_grid_blackPjdd, @function
_Z17update_grid_blackPjdd:
.LFB2048:
	.cfi_startproc
	endbr64
	pushq	%r14
	.cfi_def_cfa_offset 16
	.cfi_offset 14, -16
	movq	%xmm0, %r14
	pushq	%r13
	.cfi_def_cfa_offset 24
	.cfi_offset 13, -24
	pushq	%r12
	.cfi_def_cfa_offset 32
	.cfi_offset 12, -32
	movq	%rdi, %r12
	pushq	%rbp
	.cfi_def_cfa_offset 40
	.cfi_offset 6, -40
	movl	$1, %ebp
	pushq	%rbx
	.cfi_def_cfa_offset 48
	.cfi_offset 3, -48
	subq	$16, %rsp
	.cfi_def_cfa_offset 64
.L44:
	movl	%ebp, %r13d
	incl	%ebp
	movl	%ebp, %ebx
	andl	$1, %ebx
	incl	%ebx
.L43:
	movl	%ebx, %edx
	movq	%r14, %xmm0
	movl	%r13d, %esi
	movq	%r12, %rdi
	addl	$2, %ebx
	movsd	%xmm1, 8(%rsp)
	call	_Z16update_multispinPjiidd
	cmpl	$148, %ebx
	movsd	8(%rsp), %xmm1
	jle	.L43
	cmpl	$149, %ebp
	jne	.L44
	addq	$16, %rsp
	.cfi_def_cfa_offset 48
	popq	%rbx
	.cfi_def_cfa_offset 40
	popq	%rbp
	.cfi_def_cfa_offset 32
	popq	%r12
	.cfi_def_cfa_offset 24
	popq	%r13
	.cfi_def_cfa_offset 16
	popq	%r14
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2048:
	.size	_Z17update_grid_blackPjdd, .-_Z17update_grid_blackPjdd
	.section	.rodata.str1.1,"aMS",@progbits,1
.LC1:
	.string	" "
.LC2:
	.string	"\342\226\210"
.LC3:
	.string	"\n"
	.text
	.globl	_Z15multidump_firstPj
	.type	_Z15multidump_firstPj, @function
_Z15multidump_firstPj:
.LFB2049:
	.cfi_startproc
	endbr64
	pushq	%r14
	.cfi_def_cfa_offset 16
	.cfi_offset 14, -16
	leaq	.LC2(%rip), %r14
	pushq	%r13
	.cfi_def_cfa_offset 24
	.cfi_offset 13, -24
	movq	%rdi, %r13
	pushq	%r12
	.cfi_def_cfa_offset 32
	.cfi_offset 12, -32
	pushq	%rbp
	.cfi_def_cfa_offset 40
	.cfi_offset 6, -40
	pushq	%rbx
	.cfi_def_cfa_offset 48
	.cfi_offset 3, -48
	xorl	%ebx, %ebx
.L49:
	leaq	0(%r13,%rbx,4), %r12
	xorl	%ebp, %ebp
.L52:
	leaq	.LC1(%rip), %rsi
	testb	$1, (%r12)
	je	.L56
	movq	%r14, %rsi
.L56:
	movl	$2, %edi
	xorl	%eax, %eax
	incl	%ebp
	addq	$600, %r12
	call	__printf_chk@PLT
	cmpl	$150, %ebp
	jne	.L52
	leaq	.LC3(%rip), %rbp
	movl	$2, %edi
	xorl	%eax, %eax
	incq	%rbx
	movq	%rbp, %rsi
	call	__printf_chk@PLT
	cmpq	$150, %rbx
	jne	.L49
	popq	%rbx
	.cfi_def_cfa_offset 40
	movq	%rbp, %rsi
	movl	$2, %edi
	popq	%rbp
	.cfi_def_cfa_offset 32
	xorl	%eax, %eax
	popq	%r12
	.cfi_def_cfa_offset 24
	popq	%r13
	.cfi_def_cfa_offset 16
	popq	%r14
	.cfi_def_cfa_offset 8
	jmp	__printf_chk@PLT
	.cfi_endproc
.LFE2049:
	.size	_Z15multidump_firstPj, .-_Z15multidump_firstPj
	.section	.rodata.str1.1
.LC4:
	.string	"grid on bit %i (out of %i):\n"
	.text
	.globl	_Z15multidump_a_fewPj
	.type	_Z15multidump_a_fewPj, @function
_Z15multidump_a_fewPj:
.LFB2050:
	.cfi_startproc
	endbr64
	pushq	%r15
	.cfi_def_cfa_offset 16
	.cfi_offset 15, -16
	pushq	%r14
	.cfi_def_cfa_offset 24
	.cfi_offset 14, -24
	pushq	%r13
	.cfi_def_cfa_offset 32
	.cfi_offset 13, -32
	pushq	%r12
	.cfi_def_cfa_offset 40
	.cfi_offset 12, -40
	movq	%rdi, %r12
	pushq	%rbp
	.cfi_def_cfa_offset 48
	.cfi_offset 6, -48
	pushq	%rbx
	.cfi_def_cfa_offset 56
	.cfi_offset 3, -56
	xorl	%ebx, %ebx
	pushq	%rdx
	.cfi_def_cfa_offset 64
.L63:
	movl	%ebx, %ebp
	incl	%ebx
	movl	$32, %ecx
	movl	$2, %edi
	movl	%ebx, %edx
	leaq	.LC4(%rip), %rsi
	xorl	%eax, %eax
	movl	$1, %r15d
	call	__printf_chk@PLT
	movl	%ebp, %ecx
	xorl	%ebp, %ebp
	sall	%cl, %r15d
.L58:
	leaq	(%r12,%rbp,4), %r14
	xorl	%r13d, %r13d
.L61:
	movl	%r15d, %eax
	andl	(%r14), %eax
	leaq	.LC1(%rip), %rsi
	movl	$2, %edi
	je	.L67
	leaq	.LC2(%rip), %rsi
	movl	$2, %edi
	xorl	%eax, %eax
.L67:
	call	__printf_chk@PLT
	incl	%r13d
	addq	$600, %r14
	cmpl	$150, %r13d
	jne	.L61
	leaq	.LC3(%rip), %r13
	movl	$2, %edi
	xorl	%eax, %eax
	incq	%rbp
	movq	%r13, %rsi
	call	__printf_chk@PLT
	cmpq	$150, %rbp
	jne	.L58
	xorl	%eax, %eax
	movq	%r13, %rsi
	movl	$2, %edi
	call	__printf_chk@PLT
	cmpl	$5, %ebx
	jne	.L63
	popq	%rax
	.cfi_def_cfa_offset 56
	popq	%rbx
	.cfi_def_cfa_offset 48
	popq	%rbp
	.cfi_def_cfa_offset 40
	popq	%r12
	.cfi_def_cfa_offset 32
	popq	%r13
	.cfi_def_cfa_offset 24
	popq	%r14
	.cfi_def_cfa_offset 16
	popq	%r15
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2050:
	.size	_Z15multidump_a_fewPj, .-_Z15multidump_a_fewPj
	.globl	_Z26measure_1bit_magnetizationPji
	.type	_Z26measure_1bit_magnetizationPji, @function
_Z26measure_1bit_magnetizationPji:
.LFB2051:
	.cfi_startproc
	endbr64
	movl	%esi, %ecx
	addq	$4, %rdi
	xorps	%xmm0, %xmm0
	movl	$1, %r9d
	movsd	.LC6(%rip), %xmm2
.L69:
	movq	%rdi, %r8
	movl	$1, %edx
.L70:
	movl	600(%r8), %eax
	incl	%edx
	addq	$600, %r8
	shrl	%cl, %eax
	andl	$1, %eax
	cvtsi2sdl	%eax, %xmm1
	addsd	%xmm1, %xmm1
	subsd	%xmm2, %xmm1
	addsd	%xmm1, %xmm0
	cmpl	$149, %edx
	jne	.L70
	incl	%r9d
	addq	$4, %rdi
	cmpl	$149, %r9d
	jne	.L69
	divsd	.LC7(%rip), %xmm0
	ret
	.cfi_endproc
.LFE2051:
	.size	_Z26measure_1bit_magnetizationPji, .-_Z26measure_1bit_magnetizationPji
	.globl	_Z28update_magnetization_trackerP11multiavg_trPji
	.type	_Z28update_magnetization_trackerP11multiavg_trPji, @function
_Z28update_magnetization_trackerP11multiavg_trPji:
.LFB2052:
	.cfi_startproc
	endbr64
	movslq	%edx, %rdx
	movq	%rsi, %r11
	xorl	%esi, %esi
	salq	$8, %rdx
	leaq	(%rdi,%rdx), %r10
.L74:
	movq	%r11, %rdi
	addq	$8, %r10
	call	_Z26measure_1bit_magnetizationPji
	movsd	-8(%r10), %xmm1
	incl	%esi
	addsd	%xmm0, %xmm1
	mulsd	%xmm0, %xmm0
	addsd	760(%r10), %xmm0
	movsd	%xmm1, -8(%r10)
	movsd	%xmm0, 760(%r10)
	cmpl	$32, %esi
	jne	.L74
	ret
	.cfi_endproc
.LFE2052:
	.size	_Z28update_magnetization_trackerP11multiavg_trPji, .-_Z28update_magnetization_trackerP11multiavg_trPji
	.section	.rodata.str1.1
.LC8:
	.string	"r"
.LC9:
	.string	"params.txt"
.LC10:
	.string	"temperature %f\ntemperature_start %f\ncoupling %f\nsimulation_t_max %i\nthermalization_time %i\ntime_between_measurements %i\nbase_random_seed %i\n"
.LC11:
	.string	"%f\n"
.LC12:
	.string	"%i\n"
.LC16:
	.string	"w"
.LC17:
	.string	"results.txt"
.LC18:
	.string	"# cpu2\n"
.LC19:
	.string	"# hard-coded parameters:\n# linear_size: %i\n# spin_coding_size: %i\n"
.LC20:
	.string	"# parameters:\n# temperature: %f\n#temp_start: %f\n# coupling: %f\n# repetitions: %i\n"
.LC21:
	.string	"# simulation_t_max: %i\n# thermalization_time: %i\n# time_between_measurements: %i\n# base_random_seed: %i\n"
.LC22:
	.string	"# extra:\n# area: %i\n# active_spins_excluding_boundaries:%i\n# total_independent_sims: %i\n"
.LC23:
	.string	"# simulation %i\n"
.LC24:
	.string	"#    waiting thermalization for the first %i sim steps.\n"
.LC25:
	.string	"#    finished thermalization. running %i more simulation steps and performing %f measures.\n"
.LC26:
	.string	"# end simulation %i\n"
.LC27:
	.string	"# average of simulation %i\n: %f +- %f\n"
.LC29:
	.string	"# overall average \n: %f +- %f\n"
	.section	.text.startup,"ax",@progbits
	.globl	main
	.type	main, @function
main:
.LFB2053:
	.cfi_startproc
	endbr64
	pushq	%r15
	.cfi_def_cfa_offset 16
	.cfi_offset 15, -16
	pushq	%r14
	.cfi_def_cfa_offset 24
	.cfi_offset 14, -24
	pushq	%r13
	.cfi_def_cfa_offset 32
	.cfi_offset 13, -32
	pushq	%r12
	.cfi_def_cfa_offset 40
	.cfi_offset 12, -40
	pushq	%rbp
	.cfi_def_cfa_offset 48
	.cfi_offset 6, -48
	pushq	%rbx
	.cfi_def_cfa_offset 56
	.cfi_offset 3, -56
	leaq	-180224(%rsp), %r11
	.cfi_def_cfa 11, 180280
.LPSRL0:
	subq	$4096, %rsp
	orq	$0, (%rsp)
	cmpq	%r11, %rsp
	jne	.LPSRL0
	.cfi_def_cfa_register 7
	subq	$2968, %rsp
	.cfi_def_cfa_offset 183248
	leaq	.LC8(%rip), %rsi
	leaq	.LC9(%rip), %rdi
	leaq	.LC11(%rip), %rbp
	leaq	.LC23(%rip), %r13
	movq	%fs:40, %rax
	movq	%rax, 183176(%rsp)
	xorl	%eax, %eax
	call	fopen@PLT
	leaq	60(%rsp), %rcx
	leaq	56(%rsp), %rdx
	movq	%rax, %rbx
	pushq	%rax
	.cfi_def_cfa_offset 183256
	leaq	.LC10(%rip), %rsi
	movq	%rbx, %rdi
	leaq	92(%rsp), %rax
	pushq	%rax
	.cfi_def_cfa_offset 183264
	leaq	96(%rsp), %rax
	pushq	%rax
	.cfi_def_cfa_offset 183272
	leaq	100(%rsp), %rax
	pushq	%rax
	.cfi_def_cfa_offset 183280
	xorl	%eax, %eax
	leaq	104(%rsp), %r9
	leaq	96(%rsp), %r8
	call	__isoc23_fscanf@PLT
	addq	$32, %rsp
	.cfi_def_cfa_offset 183248
	movq	%rbp, %rsi
	movb	$1, %al
	movl	$2, %edi
	cvtss2sd	56(%rsp), %xmm0
	leaq	3176(%rsp), %r12
	call	__printf_chk@PLT
	movq	%rbp, %rsi
	movl	$2, %edi
	movb	$1, %al
	cvtss2sd	60(%rsp), %xmm0
	call	__printf_chk@PLT
	movq	%rbp, %rsi
	movb	$1, %al
	movl	$2, %edi
	cvtss2sd	64(%rsp), %xmm0
	leaq	.LC12(%rip), %rbp
	call	__printf_chk@PLT
	movl	72(%rsp), %edx
	movq	%rbp, %rsi
	xorl	%eax, %eax
	movl	$2, %edi
	call	__printf_chk@PLT
	movl	76(%rsp), %edx
	movq	%rbp, %rsi
	xorl	%eax, %eax
	movl	$2, %edi
	call	__printf_chk@PLT
	movl	80(%rsp), %edx
	movq	%rbp, %rsi
	xorl	%eax, %eax
	movl	$2, %edi
	call	__printf_chk@PLT
	movl	84(%rsp), %edx
	movq	%rbp, %rsi
	xorl	%eax, %eax
	movl	$2, %edi
	call	__printf_chk@PLT
	movq	%rbx, %rdi
	call	fclose@PLT
	movl	84(%rsp), %edi
	call	srand@PLT
	movq	%r12, %rdi
	call	_Z12init_t0_gridPj
	cvtss2sd	64(%rsp), %xmm1
	movaps	%xmm1, %xmm0
	movq	.LC14(%rip), %xmm3
	mulsd	.LC13(%rip), %xmm0
	cvtss2sd	56(%rsp), %xmm2
	movsd	%xmm1, 16(%rsp)
	movsd	%xmm2, 8(%rsp)
	xorps	%xmm3, %xmm0
	divsd	%xmm2, %xmm0
	call	exp@PLT
	movsd	16(%rsp), %xmm1
	mulsd	.LC15(%rip), %xmm1
	movq	.LC14(%rip), %xmm3
	movsd	8(%rsp), %xmm2
	movsd	%xmm0, 24(%rsp)
	xorps	%xmm3, %xmm1
	movaps	%xmm1, %xmm0
	divsd	%xmm2, %xmm0
	call	exp@PLT
	leaq	.LC16(%rip), %rsi
	leaq	.LC17(%rip), %rdi
	movsd	%xmm0, 32(%rsp)
	call	fopen@PLT
	leaq	.LC18(%rip), %rdx
	movl	$2, %esi
	movq	%rax, 8(%rsp)
	movq	%rax, %rdi
	xorl	%eax, %eax
	call	__fprintf_chk@PLT
	movq	8(%rsp), %rdi
	xorl	%eax, %eax
	movl	$32, %r8d
	movl	$150, %ecx
	leaq	.LC19(%rip), %rdx
	movl	$2, %esi
	call	__fprintf_chk@PLT
	movq	8(%rsp), %rdi
	movl	$3, %ecx
	leaq	.LC20(%rip), %rdx
	movl	$2, %esi
	movb	$3, %al
	cvtss2sd	56(%rsp), %xmm0
	cvtss2sd	64(%rsp), %xmm2
	cvtss2sd	60(%rsp), %xmm1
	call	__fprintf_chk@PLT
	movl	$2, %esi
	pushq	%rdx
	.cfi_def_cfa_offset 183256
	movl	92(%rsp), %eax
	leaq	.LC21(%rip), %rdx
	pushq	%rax
	.cfi_def_cfa_offset 183264
	movl	96(%rsp), %r9d
	xorl	%eax, %eax
	movl	92(%rsp), %r8d
	movq	24(%rsp), %rdi
	movl	88(%rsp), %ecx
	call	__fprintf_chk@PLT
	popq	%rcx
	.cfi_def_cfa_offset 183256
	popq	%rsi
	.cfi_def_cfa_offset 183248
	movl	$22500, %ecx
	movq	8(%rsp), %rdi
	leaq	.LC22(%rip), %rdx
	movl	$2, %esi
	xorl	%eax, %eax
	movl	$96, %r9d
	movl	$21904, %r8d
	leaq	88(%rsp), %r15
	call	__fprintf_chk@PLT
	movl	72(%rsp), %eax
	subl	76(%rsp), %eax
	movq	%r15, %rdi
	cltd
	xorl	%ebp, %ebp
	idivl	80(%rsp)
	cvtsi2sdl	%eax, %xmm5
	movl	%eax, %esi
	movsd	%xmm5, 40(%rsp)
	call	_Z15new_multiavg_tri
.L82:
	movl	84(%rsp), %edi
	movl	%ebp, %r14d
	xorl	%ebx, %ebx
	addl	%ebp, %edi
	incl	%ebp
	call	srand@PLT
	movl	%ebp, %edx
	movl	$22500, %ecx
	movq	%r12, %rsi
	leaq	93176(%rsp), %rdi
	xorl	%eax, %eax
	rep movsl
	movq	%r13, %rsi
	movl	$2, %edi
	call	__printf_chk@PLT
	movl	76(%rsp), %edx
	movl	$2, %edi
	xorl	%eax, %eax
	leaq	.LC24(%rip), %rsi
	call	__printf_chk@PLT
	leaq	93176(%rsp), %rax
	movq	%rax, 16(%rsp)
.L77:
	movl	76(%rsp), %eax
	cmpl	%ebx, %eax
	jle	.L88
	movsd	32(%rsp), %xmm1
	movsd	24(%rsp), %xmm0
	incl	%ebx
	movq	16(%rsp), %rdi
	call	_Z17update_grid_blackPjdd
	movsd	32(%rsp), %xmm1
	movsd	24(%rsp), %xmm0
	movq	16(%rsp), %rdi
	call	_Z17update_grid_whitePjdd
	jmp	.L77
.L88:
	movl	72(%rsp), %edx
	movsd	40(%rsp), %xmm0
	movl	$2, %edi
	leaq	.LC25(%rip), %rsi
	subl	%eax, %edx
	movb	$1, %al
	call	__printf_chk@PLT
.L79:
	cmpl	%ebx, 72(%rsp)
	jle	.L89
	movsd	32(%rsp), %xmm1
	movsd	24(%rsp), %xmm0
	movq	16(%rsp), %rdi
	call	_Z17update_grid_blackPjdd
	movsd	32(%rsp), %xmm1
	movsd	24(%rsp), %xmm0
	movq	16(%rsp), %rdi
	call	_Z17update_grid_whitePjdd
	movl	%ebx, %eax
	cltd
	idivl	80(%rsp)
	testl	%edx, %edx
	jne	.L80
	movq	16(%rsp), %rsi
	movl	%r14d, %edx
	movq	%r15, %rdi
	call	_Z28update_magnetization_trackerP11multiavg_trPji
.L80:
	incl	%ebx
	jmp	.L79
.L89:
	xorl	%eax, %eax
	movl	%ebp, %edx
	leaq	.LC26(%rip), %rsi
	movl	$2, %edi
	call	__printf_chk@PLT
	cmpl	$3, %ebp
	jne	.L82
	xorps	%xmm3, %xmm3
	movl	$1, %ebx
	leaq	.LC27(%rip), %rbp
	movaps	%xmm3, %xmm2
.L83:
	leaq	1632(%rsp), %rdi
	movl	$386, %ecx
	movq	%r15, %rsi
	movsd	%xmm2, 40(%rsp)
	rep movsl
	leaq	88(%rsp), %rsi
	leaq	1632(%rsp), %rax
	movl	$386, %ecx
	cvtsi2sdl	1624(%rsp), %xmm4
	movq	%rax, %rdi
	movsd	%xmm3, 32(%rsp)
	movsd	1624(%rsp,%rbx,8), %xmm0
	rep movsl
	movsd	1624(%rsp,%rbx,8), %xmm1
	divsd	%xmm4, %xmm0
	divsd	%xmm4, %xmm1
	movsd	%xmm0, 24(%rsp)
	movsd	2392(%rsp,%rbx,8), %xmm0
	divsd	%xmm4, %xmm0
	mulsd	%xmm1, %xmm1
	subsd	%xmm1, %xmm0
	call	sqrt@PLT
	movq	8(%rsp), %rdi
	movl	%ebx, %ecx
	movq	%rbp, %rdx
	movaps	%xmm0, %xmm1
	movsd	24(%rsp), %xmm0
	movl	$2, %esi
	movb	$2, %al
	incq	%rbx
	call	__fprintf_chk@PLT
	movsd	24(%rsp), %xmm0
	movsd	32(%rsp), %xmm3
	movsd	40(%rsp), %xmm2
	addsd	24(%rsp), %xmm2
	mulsd	%xmm0, %xmm0
	addsd	%xmm0, %xmm3
	cmpq	$97, %rbx
	jne	.L83
	movsd	.LC28(%rip), %xmm1
	divsd	%xmm1, %xmm2
	divsd	%xmm1, %xmm3
	movaps	%xmm2, %xmm1
	movsd	%xmm2, 24(%rsp)
	mulsd	%xmm2, %xmm1
	movaps	%xmm3, %xmm0
	subsd	%xmm1, %xmm0
	call	sqrt@PLT
	movsd	24(%rsp), %xmm2
	movq	8(%rsp), %rdi
	movb	$2, %al
	movaps	%xmm0, %xmm1
	leaq	.LC29(%rip), %rdx
	movl	$2, %esi
	movaps	%xmm2, %xmm0
	call	__fprintf_chk@PLT
	movq	16(%rsp), %rdi
	call	_Z15multidump_a_fewPj
	movq	183176(%rsp), %rax
	subq	%fs:40, %rax
	je	.L84
	call	__stack_chk_fail@PLT
.L84:
	addq	$183192, %rsp
	.cfi_def_cfa_offset 56
	xorl	%eax, %eax
	popq	%rbx
	.cfi_def_cfa_offset 48
	popq	%rbp
	.cfi_def_cfa_offset 40
	popq	%r12
	.cfi_def_cfa_offset 32
	popq	%r13
	.cfi_def_cfa_offset 24
	popq	%r14
	.cfi_def_cfa_offset 16
	popq	%r15
	.cfi_def_cfa_offset 8
	ret
	.cfi_endproc
.LFE2053:
	.size	main, .-main
	.type	_ZL24__sti____cudaRegisterAllv, @function
_ZL24__sti____cudaRegisterAllv:
.LFB2079:
	.cfi_startproc
	endbr64
	pushq	%rax
	.cfi_def_cfa_offset 16
	leaq	_ZL15__fatDeviceText(%rip), %rdi
	call	__cudaRegisterFatBinary@PLT
	movq	%rax, %rdi
	movq	%rax, _ZL20__cudaFatCubinHandle(%rip)
	call	__cudaRegisterFatBinaryEnd@PLT
	leaq	_ZL26__cudaUnregisterBinaryUtilv(%rip), %rdi
	popq	%rdx
	.cfi_def_cfa_offset 8
	jmp	atexit@PLT
	.cfi_endproc
.LFE2079:
	.size	_ZL24__sti____cudaRegisterAllv, .-_ZL24__sti____cudaRegisterAllv
	.section	.init_array,"aw"
	.align 8
	.quad	_ZL24__sti____cudaRegisterAllv
	.section	.nvFatBinSegment,"aw"
	.align 8
	.type	_ZL15__fatDeviceText, @object
	.size	_ZL15__fatDeviceText, 24
_ZL15__fatDeviceText:
	.long	1180844977
	.long	1
	.quad	fatbinData
	.quad	0
	.local	_ZL20__cudaFatCubinHandle
	.comm	_ZL20__cudaFatCubinHandle,8,8
	.section	.rodata.cst8,"aM",@progbits,8
	.align 8
.LC0:
	.long	-4194304
	.long	1105199103
	.align 8
.LC6:
	.long	0
	.long	1072693248
	.align 8
.LC7:
	.long	0
	.long	1087726592
	.align 8
.LC13:
	.long	0
	.long	1074790400
	.section	.rodata.cst16,"aM",@progbits,16
	.align 16
.LC14:
	.long	0
	.long	-2147483648
	.long	0
	.long	0
	.section	.rodata.cst8
	.align 8
.LC15:
	.long	0
	.long	1075838976
	.align 8
.LC28:
	.long	0
	.long	1079508992
	.ident	"GCC: (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0"
	.section	.note.GNU-stack,"",@progbits
	.section	.note.gnu.property,"a"
	.align 8
	.long	1f - 0f
	.long	4f - 1f
	.long	5
0:
	.string	"GNU"
1:
	.align 8
	.long	0xc0000002
	.long	3f - 2f
2:
	.long	0x3
3:
	.align 8
4:


#include <hip/hip_runtime.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>

// hard parameters
#define L 150
#define MULTISPIN unsigned int
#define MULTISIZE 32
// #define MULTISPIN unsigned long int
// #define MULTISIZE 64

#define STEPS_REPEAT 3

const int AREA = L*L;
const int NTOT = (L-2)*(L-2);


//external parameters

struct parameters {
    float t;
    float t_start;
    float j;
    int steps_repeat;
    int t_max_sim;
    int t_measure_wait;
    int t_measure_interval;
    int seed;
};



// average tracker struct
struct avg_tr {
    double sum;
    double sum_squares;
    int n;
};
static inline struct avg_tr new_avg_tr(int locn) {
    struct avg_tr a = { .sum = 0, .sum_squares = 0, .n = locn};
    return a;
}
// if the numbers overflow, then it would be necessary to divide by N before summing
// however it's faster the other way
static inline void update_avg(struct avg_tr * tr_p, double newval) {
    tr_p->sum +=  newval;
    tr_p->sum_squares += (newval*newval);
}
static inline double average( struct avg_tr tr) {
    return (tr.sum)/((double) tr.n) ;
}
static inline double stdev( struct avg_tr tr) {
    return sqrt(  ( tr.sum_squares)/((double) tr.n)  -  pow(( (tr.sum)/((double) tr.n) ),2)  );
}
// static inline double variance( struct avg_tr tr) {
//     return (  ( tr.sum_squares)/((double) tr.n)  -  pow(( (tr.sum)/((double) tr.n) ),2)  );
// }

//multispin averages, hard-coded to track a number MULTISPIN * STEPS_REPEAT of values
struct multiavg_tr {
    double sum[MULTISIZE * STEPS_REPEAT];
    double sum_squares[MULTISIZE * STEPS_REPEAT];
    int n; // number of terms in the avg
};
// localn is not multisize*steps_repeat, it's the number of terms that will contribute to each avg ...
struct multiavg_tr new_multiavg_tr(int localn) {
    struct multiavg_tr a;
    for(int k=0; k<MULTISIZE * STEPS_REPEAT; k++ ) {
        a.sum[k] = 0;
        a.sum_squares[k] = 0;
    }
    a.n = localn;
    return a;
}
// must be 0 =< k < MULTISIZE * STEPS_REPEAT
static inline void update_multiavg(struct multiavg_tr * tr_p, double newval, int k) {
    tr_p->sum[k] +=  newval;
    tr_p->sum_squares[k] += (newval*newval);
}
static inline double multiaverage( struct multiavg_tr tr, int k) {
    return (tr.sum[k])/((double) tr.n) ;
}
static inline double multistdev( struct multiavg_tr tr, int k) {
    return sqrt(  ( tr.sum_squares[k])/((double) tr.n)  -  pow(( (tr.sum[k])/((double) tr.n) ),2)  );
}
// static inline double multivariance( struct multiavg_tr tr, int k) {
//     return (  ( tr.sum_squares[k])/((double) tr.n)  -  pow(( (tr.sum[k])/((double) tr.n) ),2)  );
// }




double unitrand(){
    return (double)rand() / (double)RAND_MAX;
}

// index has to be less that MULTISIZE
static inline void set_spin_1 (MULTISPIN * multi, int index) {
    *multi |= 1 << index;
}
static inline void set_spin_0 (MULTISPIN * multi, int index) {
    *multi &= ~(1 << index);
}
static inline MULTISPIN read_spin(MULTISPIN multi, int index) {
    return ((multi >> index) & 1);
}

// each bit exp8 and exp8 describes the Metropolis RNG result for that bit,
// specifying if the random r is bigger or smaller than the relevant values e^(4J/kT) and e^(8J/kT) (passed from outside)
static inline MULTISPIN generate_exp4_mask(double exp4, double exp8, double random_number) {
    MULTISPIN res;
    for(int k=0; k<MULTISIZE; k++) {
        if( exp4 > random_number && random_number > exp8) { // this is taken from the article and works. the version below might not but simplifies some things
        // if( exp4 > random_number) {
            set_spin_1(&res, k);
        } else {
            set_spin_0(&res, k);
        }
    }
    return res;
}
static inline MULTISPIN generate_exp8_mask(double exp8, double random_number) {
    MULTISPIN res;
    for(int k=0; k<MULTISIZE; k++) {
        if( random_number < exp8 ) {
            set_spin_1(&res, k);
        } else {
            set_spin_0(&res, k);
        }
    }
    return res;
}

MULTISPIN init_random_multispin() {
    return (MULTISPIN) rand(); // just spam random bits
}
void init_random_grid(MULTISPIN grid[L*L]) {
    for(int x = 0; x<L; x++) {
        for(int y = 0; y<L; y++) {
            grid[x+y*L] = init_random_multispin();
        }
    }
}


MULTISPIN init_t0_multispin() {
    return (MULTISPIN) 0; // should be all zeros for all sensible multispin types
}
void init_t0_grid(MULTISPIN grid[L*L]) {
    for(int x = 0; x<L; x++) {
        for(int y = 0; y<L; y++) {
            grid[x+y*L] = init_t0_multispin();
        }
    }
}

// static inline void flip(MULTISPIN grid[L*L], int x, int y) {
//     grid[x+y*L] = ~grid[x+y*L];
// }

// can segfault 
static inline MULTISPIN grid_step(MULTISPIN grid[L*L], int x, int y, int xstep, int ystep) {
    return grid[(x+xstep)  + (y+ystep)*L];
}


// segfault if applied to an edge spin, must be called only on the inner L-1 grid
void update_multispin(MULTISPIN grid[L*L], int x, int y, double exp4, double exp8 ) {

    MULTISPIN s0 = grid[x+y*L];
    
    double ur = unitrand(); 
    MULTISPIN exp4_mask = generate_exp4_mask(exp4, exp8, ur); // here
    MULTISPIN exp8_mask = generate_exp8_mask(exp8, ur);

    // "energy variables" indicating whether s0 is equal or opposite to each of its 4 neighbours 
    MULTISPIN i1 = s0 ^ grid_step(grid, x, y, 1, 0);
    MULTISPIN i2 = s0 ^ grid_step(grid, x, y, -1, 0);
    MULTISPIN i3 = s0 ^ grid_step(grid, x, y, 0, 1);
    MULTISPIN i4 = s0 ^ grid_step(grid, x, y, 0, -1);
    
    // bit sums with carry over between the i variables
    MULTISPIN j1 = i1 & i2;
    MULTISPIN j2 = i1 ^ i2;
    MULTISPIN j3 = i3 & i4;
    MULTISPIN j4 = i3 ^ i4;

    // logic for deciding whether to flip s0 or not
    MULTISPIN flip_mask = ( ((j1 | j3) | (~(j1^j3) & (j2&j4))  )  |   ((j2 | j4) & exp4_mask  )   |   exp8_mask );

    grid[x+y*L] = grid[x+y*L] ^ flip_mask;

    // explanation:
    // spins | i1234 | deltaE | j1 j2  j3 j4 |
    //   1   |   1   |        |              |    
    //  101  |  1 1  |   -8   |  1 0    1 0  |                   
    //   1   |   1   |        |              |
    //                                                         
    //   0   |   0   |        |              |    
    //  101  |  1 1  |   -4   |  0 1    1 0  |         (j1 | j3)          
    //   1   |   1   |        |              |
    //                                                         
    //   0   |   0   |        |  0 0    1 0  |    
    //  001  |  0 1  |    0   |      or      |-------------------------                  
    //   1   |   1   |        |  0 1    0 1  |      ~(j1^j3) & (j2&j4))
    //------------------------------------------------------------------
    //                                                        
    //   0   |   0   |        |              |    
    //  000  |  0 0  |    +4  |              |       (j2 | j4) & exp4      
    //   1   |   1   |        |              |
    //------------------------------------------------------------------ 
    //                                                        
    //   0   |   0   |        |              |    
    //  000  |  0 0  |    +8  |  0 0    0 0  |           exp8       
    //   0   |   0   |        |              |

    // the first 2 cases are detected by (j1 | j3) and lead to the spin flip regardless of the RNG roll.
    // the deltaH = 0 case can result in two different forms for the j's depending on ho the spins are paired. 
    //   the first of these is correctly picked up by (j1 | j3), while the second needs its own expression ~(j1^j3) & (j2&j4))
    // in the 4th case, detected by (j2 | j4), the spin is flipped only if the RNG roll is lucky enough (exp4 = 1)
    // if we still haven't flipped, we get to the last case. here the spin is flipped only if the RNG roll gives the luckiest result (exp8 = 1).
    
}

// checkerboard patterns
void update_grid_white(MULTISPIN grid[L*L], double exp4, double exp8 ) {
    for(int x = 1; x<L-1; x+=1) {
        for(int y = (1 + x%2) ; y<L-1; y+=2) {
            update_multispin(grid, x, y, exp4, exp8);
        }
    }
}
void update_grid_black(MULTISPIN grid[L*L], double exp4, double exp8 ) {
    for(int x = 1; x<L-1; x+=1) {
        for(int y = (1 + (x+1)%2) ; y<L-1; y+=2) {
            update_multispin(grid, x, y, exp4, exp8);
        }
    }
}

// non GPU function
void multidump_first(MULTISPIN grid[L*L]) {
    // printf("first bit grid (out of %i):\n", MULTISIZE);
    for(int x = 0; x<L; x++) {
        for(int y = 0; y<L; y++) {
            
            if(( grid[x+y*L] & 1 ) == 0) printf(" ");
            else printf("█");

        }
        printf("\n");
    }
    printf("\n");
}

// non GPU function
void multidump_a_few(MULTISPIN grid[L*L]) {
    for(int k=0; k<5; k++) {
        printf("grid on bit %i (out of %i):\n", k+1, MULTISIZE);
        for(int x = 0; x<L; x++) {
            for(int y = 0; y<L; y++) {
                
                if(( grid[x+y*L] & (1 << k) ) == 0) printf(" ");
                else printf("█");

            }
            printf("\n");
        }
        printf("\n");
    }
}

// non GPU
double measure_1bit_magnetization(MULTISPIN grid[L*L], int multi_index) {
    double lmagn = 0;
    for(int x = 1; x<L-1; x++) {
        for(int y = 1; y<L-1; y++) {
            double bit = (double) read_spin(grid[x+y*L], multi_index); 
            lmagn = lmagn + ((bit*2.) -1.);
        }
    }

    return (((double) lmagn ) / (double) NTOT) ;
}

// as usual, the number of independent measures is hardcoded to MULTISIZE * STEPS_REPEAT.
// this function measures a single multispin, updating a chunk of the tracker. (for example the first half if rep_steps is 2)
void update_magnetization_tracker( struct multiavg_tr * tr_p, MULTISPIN grid[L*L], int block_count) {
    for( int k=0; k < MULTISIZE; k++) {
        double mag = measure_1bit_magnetization(grid, k);
        update_multiavg(tr_p, mag, k + MULTISIZE*block_count );
    }
}

// static inline void update_multiavg(struct multiavg_tr * tr_p, double newval, int k) {
//     tr_p->sum[k] +=  newval;
//     tr_p->sum_squares[k] += (newval*newval);
// }


int main() {
    // read params

    FILE *param_f = fopen("params.txt", "r");
    struct parameters par;

    fscanf(param_f, "temperature %f\ntemperature_start %f\ncoupling %f\nsimulation_t_max %i\nthermalization_time %i\ntime_between_measurements %i\nbase_random_seed %i\n", 
                    &(par.t),     &(par.t_start),     &(par.j),    &(par.t_max_sim),   &(par.t_measure_wait),   &(par.t_measure_interval),       &(par.seed));
    printf("%f\n", par.t);
    printf("%f\n", par.t_start);
    printf("%f\n", par.j);
    printf("%i\n", par.t_max_sim);
    printf("%i\n", par.t_measure_wait);
    printf("%i\n", par.t_measure_interval);
    printf("%i\n", par.seed);
    fclose(param_f);


    srand(par.seed);
    MULTISPIN startgrid[L*L];
    init_t0_grid(startgrid);



    const double EXP4 = exp( -(4.*par.j) / par.t);
    const double EXP8 = exp( -(8.*par.j) / par.t);

    // measure cycle
    FILE *resf = fopen("results.txt", "w");
    fprintf(resf, "# cpu2\n");
    fprintf(resf, "# hard-coded parameters:\n# linear_size: %i\n# spin_coding_size: %i\n", L, MULTISIZE);
    fprintf(resf, "# parameters:\n# temperature: %f\n#temp_start: %f\n# coupling: %f\n# repetitions: %i\n", par.t, par.t_start, par.j, STEPS_REPEAT);
    fprintf(resf, "# simulation_t_max: %i\n# thermalization_time: %i\n# time_between_measurements: %i\n# base_random_seed: %i\n",  par.t_max_sim, par.t_measure_wait, par.t_measure_interval, par.seed);
    fprintf(resf, "# extra:\n# area: %i\n# active_spins_excluding_boundaries:%i\n# total_independent_sims: %i\n", AREA, NTOT, MULTISIZE*STEPS_REPEAT);
    
    MULTISPIN grid[L*L];
    double n_measures_per_sim = (double) ((par.t_max_sim - par.t_measure_wait)/par.t_measure_interval);

    //OUTER REP LOOP  
    struct multiavg_tr single_run_avgs = new_multiavg_tr(n_measures_per_sim);

    for( int krep=0; krep< STEPS_REPEAT; krep++) {
        srand(par.seed + krep);
        memcpy(grid, startgrid, L*L*sizeof(MULTISPIN) );

        // INNER SIM LOOPS
        printf("# simulation %i\n", krep+1);
        printf("#    waiting thermalization for the first %i sim steps.\n", par.t_measure_wait);
        int ksim=0;
        for( ; ksim<par.t_measure_wait; ksim++) {
            update_grid_black(grid, EXP4, EXP8);
            update_grid_white(grid, EXP4, EXP8);
        }
        printf("#    finished thermalization. running %i more simulation steps and performing %f measures.\n",(par.t_max_sim - par.t_measure_wait), n_measures_per_sim);

        for( ; ksim<par.t_max_sim; ksim++) {
            update_grid_black(grid, EXP4, EXP8);
            update_grid_white(grid, EXP4, EXP8);
            
            if( ksim % par.t_measure_interval == 0) {
                update_magnetization_tracker(&single_run_avgs, grid, krep);
            }
        }
        // END INNER SIM LOOPS        
        printf("# end simulation %i\n", krep+1);
    }
    // END OUTER REPETITION LOOP

    struct avg_tr avg_of_blocks = new_avg_tr( MULTISIZE * STEPS_REPEAT );

    for(int k=0; k < MULTISIZE * STEPS_REPEAT; k++) {
        double lres = multiaverage(single_run_avgs, k);
        double lstdev = multistdev(single_run_avgs, k);

        fprintf(resf, "# average of simulation %i\n: %f +- %f\n", k+1, lres, lstdev);
        update_avg(&avg_of_blocks, lres);
    }
    fprintf(resf, "# overall average \n: %f +- %f\n", average(avg_of_blocks), stdev(avg_of_blocks));

    multidump_a_few(grid);





    return 0;
}


	.text
	.file	"main.hip"
	.globl	_Z15new_multiavg_tri            # -- Begin function _Z15new_multiavg_tri
	.type	_Z15new_multiavg_tri,@function
_Z15new_multiavg_tri:                   # @_Z15new_multiavg_tri
	.cfi_startproc
# %bb.0:
	pushq	%r14
	.cfi_def_cfa_offset 16
	pushq	%rbx
	.cfi_def_cfa_offset 24
	pushq	%rax
	.cfi_def_cfa_offset 32
	.cfi_offset %rbx, -24
	.cfi_offset %r14, -16
	movl	%esi, %ebx
	movq	%rdi, %r14
	movl	$1536, %edx                     # imm = 0x600
	xorl	%esi, %esi
	callq	memset@PLT
	movl	%ebx, 1536(%r14)
	movq	%r14, %rax
	addq	$8, %rsp
	.cfi_def_cfa_offset 24
	popq	%rbx
	.cfi_def_cfa_offset 16
	popq	%r14
	.cfi_def_cfa_offset 8
	retq
.Lfunc_end0:
	.size	_Z15new_multiavg_tri, .Lfunc_end0-_Z15new_multiavg_tri
	.cfi_endproc
                                        # -- End function
	.section	.rodata.cst8,"aM",@progbits,8
	.p2align	3, 0x0                          # -- Begin function _Z8unitrandv
.LCPI1_0:
	.quad	0x41dfffffffc00000              # double 2147483647
	.text
	.globl	_Z8unitrandv
	.type	_Z8unitrandv,@function
_Z8unitrandv:                           # @_Z8unitrandv
	.cfi_startproc
# %bb.0:
	pushq	%rax
	.cfi_def_cfa_offset 16
	callq	rand
	cvtsi2sd	%eax, %xmm0
	divsd	.LCPI1_0(%rip), %xmm0
	popq	%rax
	.cfi_def_cfa_offset 8
	retq
.Lfunc_end1:
	.size	_Z8unitrandv, .Lfunc_end1-_Z8unitrandv
	.cfi_endproc
                                        # -- End function
	.globl	_Z21init_random_multispinv      # -- Begin function _Z21init_random_multispinv
	.type	_Z21init_random_multispinv,@function
_Z21init_random_multispinv:             # @_Z21init_random_multispinv
	.cfi_startproc
# %bb.0:
	jmp	rand                            # TAILCALL
.Lfunc_end2:
	.size	_Z21init_random_multispinv, .Lfunc_end2-_Z21init_random_multispinv
	.cfi_endproc
                                        # -- End function
	.globl	_Z16init_random_gridPj          # -- Begin function _Z16init_random_gridPj
	.type	_Z16init_random_gridPj,@function
_Z16init_random_gridPj:                 # @_Z16init_random_gridPj
	.cfi_startproc
# %bb.0:
	pushq	%r15
	.cfi_def_cfa_offset 16
	pushq	%r14
	.cfi_def_cfa_offset 24
	pushq	%rbx
	.cfi_def_cfa_offset 32
	.cfi_offset %rbx, -32
	.cfi_offset %r14, -24
	.cfi_offset %r15, -16
	movq	%rdi, %rbx
	xorl	%r14d, %r14d
.LBB3_1:                                # %.preheader
                                        # =>This Loop Header: Depth=1
                                        #     Child Loop BB3_2 Depth 2
	movq	$-90000, %r15                   # imm = 0xFFFEA070
.LBB3_2:                                #   Parent Loop BB3_1 Depth=1
                                        # =>  This Inner Loop Header: Depth=2
	callq	rand
	movl	%eax, 90000(%rbx,%r15)
	addq	$600, %r15                      # imm = 0x258
	jne	.LBB3_2
# %bb.3:                                #   in Loop: Header=BB3_1 Depth=1
	incq	%r14
	addq	$4, %rbx
	cmpq	$150, %r14
	jne	.LBB3_1
# %bb.4:
	popq	%rbx
	.cfi_def_cfa_offset 24
	popq	%r14
	.cfi_def_cfa_offset 16
	popq	%r15
	.cfi_def_cfa_offset 8
	retq
.Lfunc_end3:
	.size	_Z16init_random_gridPj, .Lfunc_end3-_Z16init_random_gridPj
	.cfi_endproc
                                        # -- End function
	.globl	_Z17init_t0_multispinv          # -- Begin function _Z17init_t0_multispinv
	.type	_Z17init_t0_multispinv,@function
_Z17init_t0_multispinv:                 # @_Z17init_t0_multispinv
	.cfi_startproc
# %bb.0:
	xorl	%eax, %eax
	retq
.Lfunc_end4:
	.size	_Z17init_t0_multispinv, .Lfunc_end4-_Z17init_t0_multispinv
	.cfi_endproc
                                        # -- End function
	.globl	_Z12init_t0_gridPj              # -- Begin function _Z12init_t0_gridPj
	.type	_Z12init_t0_gridPj,@function
_Z12init_t0_gridPj:                     # @_Z12init_t0_gridPj
	.cfi_startproc
# %bb.0:
	xorl	%eax, %eax
.LBB5_1:                                # %.preheader
                                        # =>This Loop Header: Depth=1
                                        #     Child Loop BB5_2 Depth 2
	movq	$-90000, %rcx                   # imm = 0xFFFEA070
.LBB5_2:                                #   Parent Loop BB5_1 Depth=1
                                        # =>  This Inner Loop Header: Depth=2
	movl	$0, 90000(%rdi,%rcx)
	addq	$600, %rcx                      # imm = 0x258
	jne	.LBB5_2
# %bb.3:                                #   in Loop: Header=BB5_1 Depth=1
	incq	%rax
	addq	$4, %rdi
	cmpq	$150, %rax
	jne	.LBB5_1
# %bb.4:
	retq
.Lfunc_end5:
	.size	_Z12init_t0_gridPj, .Lfunc_end5-_Z12init_t0_gridPj
	.cfi_endproc
                                        # -- End function
	.section	.rodata.cst8,"aM",@progbits,8
	.p2align	3, 0x0                          # -- Begin function _Z16update_multispinPjiidd
.LCPI6_0:
	.quad	0x41dfffffffc00000              # double 2147483647
	.text
	.globl	_Z16update_multispinPjiidd
	.type	_Z16update_multispinPjiidd,@function
_Z16update_multispinPjiidd:             # @_Z16update_multispinPjiidd
	.cfi_startproc
# %bb.0:
	pushq	%rbp
	.cfi_def_cfa_offset 16
	pushq	%r15
	.cfi_def_cfa_offset 24
	pushq	%r14
	.cfi_def_cfa_offset 32
	pushq	%r12
	.cfi_def_cfa_offset 40
	pushq	%rbx
	.cfi_def_cfa_offset 48
	subq	$32, %rsp
	.cfi_def_cfa_offset 80
	.cfi_offset %rbx, -48
	.cfi_offset %r12, -40
	.cfi_offset %r14, -32
	.cfi_offset %r15, -24
	.cfi_offset %rbp, -16
	movaps	%xmm1, (%rsp)                   # 16-byte Spill
	movaps	%xmm0, 16(%rsp)                 # 16-byte Spill
	movl	%esi, %r14d
	movq	%rdi, %rbx
	imull	$150, %edx, %r12d
	leal	(%r12,%r14), %eax
	movslq	%eax, %r15
	movl	(%rdi,%r15,4), %ebp
	callq	rand
	movapd	(%rsp), %xmm3                   # 16-byte Reload
	xorps	%xmm0, %xmm0
	cvtsi2sd	%eax, %xmm0
	divsd	.LCPI6_0(%rip), %xmm0
	movapd	%xmm3, %xmm1
	cmpltpd	%xmm0, %xmm1
	movapd	%xmm0, %xmm2
	cmpltpd	16(%rsp), %xmm2                 # 16-byte Folded Reload
	andpd	%xmm1, %xmm2
	movd	%xmm2, %ecx
	xorl	%edx, %edx
                                        # implicit-def: $eax
.LBB6_1:                                # =>This Inner Loop Header: Depth=1
	movl	%eax, %esi
	btsl	%edx, %esi
	btrl	%edx, %eax
	testb	$1, %cl
	cmovnel	%esi, %eax
	incl	%edx
	cmpl	$32, %edx
	jne	.LBB6_1
# %bb.2:                                # %_ZL18generate_exp4_maskddd.exit
	xorl	%edx, %edx
                                        # implicit-def: $ecx
.LBB6_3:                                # =>This Inner Loop Header: Depth=1
	movl	%ecx, %esi
	btsl	%edx, %esi
	btrl	%edx, %ecx
	ucomisd	%xmm0, %xmm3
	cmoval	%esi, %ecx
	incl	%edx
	cmpl	$32, %edx
	jne	.LBB6_3
# %bb.4:                                # %_ZL18generate_exp8_maskdd.exit
	leal	1(%r15), %edx
	movslq	%edx, %rdx
	movl	(%rbx,%rdx,4), %edi
	leal	-1(%r15), %edx
	movslq	%edx, %rdx
	movl	(%rbx,%rdx,4), %esi
	movl	%esi, %edx
	xorl	%edi, %esi
	xorl	%ebp, %edi
	xorl	%ebp, %edx
	andl	%edi, %edx
	leal	(%r14,%r12), %edi
	addl	$150, %edi
	movslq	%edi, %rdi
	movl	(%rbx,%rdi,4), %edi
	movl	%edi, %r8d
	xorl	%ebp, %r8d
	leal	(%r14,%r12), %r9d
	addl	$-150, %r9d
	movslq	%r9d, %r9
	movl	(%rbx,%r9,4), %r9d
	xorl	%r9d, %ebp
	andl	%r8d, %ebp
	xorl	%edi, %r9d
	movl	%esi, %edi
	andl	%r9d, %edi
	orl	%esi, %r9d
	andl	%eax, %r9d
	orl	%ecx, %r9d
	orl	%edx, %r9d
	xorl	%ebp, %edx
	notl	%edx
	andl	%edx, %edi
	orl	%edi, %r9d
	orl	%ebp, %r9d
	xorl	%r9d, (%rbx,%r15,4)
	addq	$32, %rsp
	.cfi_def_cfa_offset 48
	popq	%rbx
	.cfi_def_cfa_offset 40
	popq	%r12
	.cfi_def_cfa_offset 32
	popq	%r14
	.cfi_def_cfa_offset 24
	popq	%r15
	.cfi_def_cfa_offset 16
	popq	%rbp
	.cfi_def_cfa_offset 8
	retq
.Lfunc_end6:
	.size	_Z16update_multispinPjiidd, .Lfunc_end6-_Z16update_multispinPjiidd
	.cfi_endproc
                                        # -- End function
	.globl	_Z17update_grid_whitePjdd       # -- Begin function _Z17update_grid_whitePjdd
	.type	_Z17update_grid_whitePjdd,@function
_Z17update_grid_whitePjdd:              # @_Z17update_grid_whitePjdd
	.cfi_startproc
# %bb.0:
	pushq	%rbp
	.cfi_def_cfa_offset 16
	pushq	%r14
	.cfi_def_cfa_offset 24
	pushq	%rbx
	.cfi_def_cfa_offset 32
	subq	$16, %rsp
	.cfi_def_cfa_offset 48
	.cfi_offset %rbx, -32
	.cfi_offset %r14, -24
	.cfi_offset %rbp, -16
	movq	%rdi, %rbx
	movl	$1, %ebp
	movsd	%xmm1, 8(%rsp)                  # 8-byte Spill
	movsd	%xmm0, (%rsp)                   # 8-byte Spill
.LBB7_1:                                # %.lr.ph.preheader
                                        # =>This Loop Header: Depth=1
                                        #     Child Loop BB7_2 Depth 2
	movl	%ebp, %r14d
	andl	$1, %r14d
	decl	%r14d
.LBB7_2:                                # %.lr.ph
                                        #   Parent Loop BB7_1 Depth=1
                                        # =>  This Inner Loop Header: Depth=2
	addl	$2, %r14d
	movq	%rbx, %rdi
	movl	%ebp, %esi
	movl	%r14d, %edx
	movsd	(%rsp), %xmm0                   # 8-byte Reload
                                        # xmm0 = mem[0],zero
	movsd	8(%rsp), %xmm1                  # 8-byte Reload
                                        # xmm1 = mem[0],zero
	callq	_Z16update_multispinPjiidd
	cmpl	$147, %r14d
	jb	.LBB7_2
# %bb.3:                                # %._crit_edge
                                        #   in Loop: Header=BB7_1 Depth=1
	incl	%ebp
	cmpl	$149, %ebp
	jne	.LBB7_1
# %bb.4:
	addq	$16, %rsp
	.cfi_def_cfa_offset 32
	popq	%rbx
	.cfi_def_cfa_offset 24
	popq	%r14
	.cfi_def_cfa_offset 16
	popq	%rbp
	.cfi_def_cfa_offset 8
	retq
.Lfunc_end7:
	.size	_Z17update_grid_whitePjdd, .Lfunc_end7-_Z17update_grid_whitePjdd
	.cfi_endproc
                                        # -- End function
	.globl	_Z17update_grid_blackPjdd       # -- Begin function _Z17update_grid_blackPjdd
	.type	_Z17update_grid_blackPjdd,@function
_Z17update_grid_blackPjdd:              # @_Z17update_grid_blackPjdd
	.cfi_startproc
# %bb.0:
	pushq	%rbp
	.cfi_def_cfa_offset 16
	pushq	%r15
	.cfi_def_cfa_offset 24
	pushq	%r14
	.cfi_def_cfa_offset 32
	pushq	%r12
	.cfi_def_cfa_offset 40
	pushq	%rbx
	.cfi_def_cfa_offset 48
	subq	$16, %rsp
	.cfi_def_cfa_offset 64
	.cfi_offset %rbx, -48
	.cfi_offset %r12, -40
	.cfi_offset %r14, -32
	.cfi_offset %r15, -24
	.cfi_offset %rbp, -16
	movq	%rdi, %rbx
	movl	$1, %r12d
	xorl	%r15d, %r15d
	movsd	%xmm1, 8(%rsp)                  # 8-byte Spill
	movsd	%xmm0, (%rsp)                   # 8-byte Spill
.LBB8_2:                                # %.lr.ph.preheader
                                        # =>This Loop Header: Depth=1
                                        #     Child Loop BB8_3 Depth 2
	movl	%r12d, %r14d
	movzbl	%r15b, %ebp
	andl	$1, %ebp
	decl	%ebp
	leal	1(%r14), %r12d
.LBB8_3:                                # %.lr.ph
                                        #   Parent Loop BB8_2 Depth=1
                                        # =>  This Inner Loop Header: Depth=2
	addl	$2, %ebp
	movq	%rbx, %rdi
	movl	%r14d, %esi
	movl	%ebp, %edx
	movsd	(%rsp), %xmm0                   # 8-byte Reload
                                        # xmm0 = mem[0],zero
	movsd	8(%rsp), %xmm1                  # 8-byte Reload
                                        # xmm1 = mem[0],zero
	callq	_Z16update_multispinPjiidd
	cmpl	$147, %ebp
	jb	.LBB8_3
# %bb.1:                                # %.loopexit
                                        #   in Loop: Header=BB8_2 Depth=1
	incb	%r15b
	cmpl	$149, %r12d
	jne	.LBB8_2
# %bb.4:
	addq	$16, %rsp
	.cfi_def_cfa_offset 48
	popq	%rbx
	.cfi_def_cfa_offset 40
	popq	%r12
	.cfi_def_cfa_offset 32
	popq	%r14
	.cfi_def_cfa_offset 24
	popq	%r15
	.cfi_def_cfa_offset 16
	popq	%rbp
	.cfi_def_cfa_offset 8
	retq
.Lfunc_end8:
	.size	_Z17update_grid_blackPjdd, .Lfunc_end8-_Z17update_grid_blackPjdd
	.cfi_endproc
                                        # -- End function
	.globl	_Z15multidump_firstPj           # -- Begin function _Z15multidump_firstPj
	.type	_Z15multidump_firstPj,@function
_Z15multidump_firstPj:                  # @_Z15multidump_firstPj
	.cfi_startproc
# %bb.0:
	pushq	%r15
	.cfi_def_cfa_offset 16
	pushq	%r14
	.cfi_def_cfa_offset 24
	pushq	%rbx
	.cfi_def_cfa_offset 32
	.cfi_offset %rbx, -32
	.cfi_offset %r14, -24
	.cfi_offset %r15, -16
	movq	%rdi, %rbx
	xorl	%r14d, %r14d
.LBB9_1:                                # %.preheader
                                        # =>This Loop Header: Depth=1
                                        #     Child Loop BB9_2 Depth 2
	movq	$-90000, %r15                   # imm = 0xFFFEA070
.LBB9_2:                                #   Parent Loop BB9_1 Depth=1
                                        # =>  This Inner Loop Header: Depth=2
	testb	$1, 90000(%rbx,%r15)
	jne	.LBB9_6
# %bb.3:                                #   in Loop: Header=BB9_2 Depth=2
	movl	$32, %edi
	callq	putchar@PLT
	jmp	.LBB9_7
.LBB9_6:                                #   in Loop: Header=BB9_2 Depth=2
	movl	$.L.str.1, %edi
	xorl	%eax, %eax
	callq	printf
.LBB9_7:                                #   in Loop: Header=BB9_2 Depth=2
	addq	$600, %r15                      # imm = 0x258
	jne	.LBB9_2
# %bb.4:                                #   in Loop: Header=BB9_1 Depth=1
	movl	$10, %edi
	callq	putchar@PLT
	incq	%r14
	addq	$4, %rbx
	cmpq	$150, %r14
	jne	.LBB9_1
# %bb.5:
	movl	$10, %edi
	popq	%rbx
	.cfi_def_cfa_offset 24
	popq	%r14
	.cfi_def_cfa_offset 16
	popq	%r15
	.cfi_def_cfa_offset 8
	jmp	putchar@PLT                     # TAILCALL
.Lfunc_end9:
	.size	_Z15multidump_firstPj, .Lfunc_end9-_Z15multidump_firstPj
	.cfi_endproc
                                        # -- End function
	.globl	_Z15multidump_a_fewPj           # -- Begin function _Z15multidump_a_fewPj
	.type	_Z15multidump_a_fewPj,@function
_Z15multidump_a_fewPj:                  # @_Z15multidump_a_fewPj
	.cfi_startproc
# %bb.0:
	pushq	%rbp
	.cfi_def_cfa_offset 16
	pushq	%r15
	.cfi_def_cfa_offset 24
	pushq	%r14
	.cfi_def_cfa_offset 32
	pushq	%r13
	.cfi_def_cfa_offset 40
	pushq	%r12
	.cfi_def_cfa_offset 48
	pushq	%rbx
	.cfi_def_cfa_offset 56
	pushq	%rax
	.cfi_def_cfa_offset 64
	.cfi_offset %rbx, -56
	.cfi_offset %r12, -48
	.cfi_offset %r13, -40
	.cfi_offset %r14, -32
	.cfi_offset %r15, -24
	.cfi_offset %rbp, -16
	movq	%rdi, %rbx
	xorl	%ebp, %ebp
.LBB10_1:                               # =>This Loop Header: Depth=1
                                        #     Child Loop BB10_2 Depth 2
                                        #       Child Loop BB10_3 Depth 3
	movl	%ebp, %r14d
	leal	1(%r14), %ebp
	movl	$.L.str.3, %edi
	movl	%ebp, %esi
	movl	$32, %edx
	xorl	%eax, %eax
	callq	printf
	movl	$1, %r15d
	movl	%r14d, %ecx
	shll	%cl, %r15d
	movq	%rbx, %r14
	xorl	%r12d, %r12d
.LBB10_2:                               # %.preheader
                                        #   Parent Loop BB10_1 Depth=1
                                        # =>  This Loop Header: Depth=2
                                        #       Child Loop BB10_3 Depth 3
	movq	$-90000, %r13                   # imm = 0xFFFEA070
.LBB10_3:                               #   Parent Loop BB10_1 Depth=1
                                        #     Parent Loop BB10_2 Depth=2
                                        # =>    This Inner Loop Header: Depth=3
	testl	%r15d, 90000(%r14,%r13)
	je	.LBB10_4
# %bb.7:                                #   in Loop: Header=BB10_3 Depth=3
	movl	$.L.str.1, %edi
	xorl	%eax, %eax
	callq	printf
	jmp	.LBB10_8
.LBB10_4:                               #   in Loop: Header=BB10_3 Depth=3
	movl	$32, %edi
	callq	putchar@PLT
.LBB10_8:                               #   in Loop: Header=BB10_3 Depth=3
	addq	$600, %r13                      # imm = 0x258
	jne	.LBB10_3
# %bb.9:                                #   in Loop: Header=BB10_2 Depth=2
	movl	$10, %edi
	callq	putchar@PLT
	incq	%r12
	addq	$4, %r14
	cmpq	$150, %r12
	jne	.LBB10_2
# %bb.5:                                #   in Loop: Header=BB10_1 Depth=1
	movl	$10, %edi
	callq	putchar@PLT
	cmpl	$5, %ebp
	jne	.LBB10_1
# %bb.6:
	addq	$8, %rsp
	.cfi_def_cfa_offset 56
	popq	%rbx
	.cfi_def_cfa_offset 48
	popq	%r12
	.cfi_def_cfa_offset 40
	popq	%r13
	.cfi_def_cfa_offset 32
	popq	%r14
	.cfi_def_cfa_offset 24
	popq	%r15
	.cfi_def_cfa_offset 16
	popq	%rbp
	.cfi_def_cfa_offset 8
	retq
.Lfunc_end10:
	.size	_Z15multidump_a_fewPj, .Lfunc_end10-_Z15multidump_a_fewPj
	.cfi_endproc
                                        # -- End function
	.section	.rodata.cst8,"aM",@progbits,8
	.p2align	3, 0x0                          # -- Begin function _Z26measure_1bit_magnetizationPji
.LCPI11_0:
	.quad	0xbff0000000000000              # double -1
.LCPI11_1:
	.quad	0x40d5640000000000              # double 21904
	.text
	.globl	_Z26measure_1bit_magnetizationPji
	.type	_Z26measure_1bit_magnetizationPji,@function
_Z26measure_1bit_magnetizationPji:      # @_Z26measure_1bit_magnetizationPji
	.cfi_startproc
# %bb.0:
	xorpd	%xmm0, %xmm0
	movl	$1, %eax
	movsd	.LCPI11_0(%rip), %xmm1          # xmm1 = mem[0],zero
.LBB11_1:                               # %.preheader
                                        # =>This Loop Header: Depth=1
                                        #     Child Loop BB11_2 Depth 2
	movl	$604, %ecx                      # imm = 0x25C
.LBB11_2:                               #   Parent Loop BB11_1 Depth=1
                                        # =>  This Inner Loop Header: Depth=2
	movl	(%rdi,%rcx), %edx
	xorl	%r8d, %r8d
	btl	%esi, %edx
	setb	%r8b
	xorps	%xmm2, %xmm2
	cvtsi2sd	%r8d, %xmm2
	addsd	%xmm2, %xmm2
	addsd	%xmm1, %xmm2
	addsd	%xmm2, %xmm0
	addq	$600, %rcx                      # imm = 0x258
	cmpq	$89404, %rcx                    # imm = 0x15D3C
	jne	.LBB11_2
# %bb.3:                                #   in Loop: Header=BB11_1 Depth=1
	incq	%rax
	addq	$4, %rdi
	cmpq	$149, %rax
	jne	.LBB11_1
# %bb.4:
	divsd	.LCPI11_1(%rip), %xmm0
	retq
.Lfunc_end11:
	.size	_Z26measure_1bit_magnetizationPji, .Lfunc_end11-_Z26measure_1bit_magnetizationPji
	.cfi_endproc
                                        # -- End function
	.section	.rodata.cst8,"aM",@progbits,8
	.p2align	3, 0x0                          # -- Begin function _Z28update_magnetization_trackerP11multiavg_trPji
.LCPI12_0:
	.quad	0xbff0000000000000              # double -1
.LCPI12_1:
	.quad	0x40d5640000000000              # double 21904
	.text
	.globl	_Z28update_magnetization_trackerP11multiavg_trPji
	.type	_Z28update_magnetization_trackerP11multiavg_trPji,@function
_Z28update_magnetization_trackerP11multiavg_trPji: # @_Z28update_magnetization_trackerP11multiavg_trPji
	.cfi_startproc
# %bb.0:
	shll	$5, %edx
	movslq	%edx, %rax
	xorl	%ecx, %ecx
	movsd	.LCPI12_0(%rip), %xmm0          # xmm0 = mem[0],zero
	movsd	.LCPI12_1(%rip), %xmm1          # xmm1 = mem[0],zero
.LBB12_1:                               # %.preheader.i.preheader
                                        # =>This Loop Header: Depth=1
                                        #     Child Loop BB12_2 Depth 2
                                        #       Child Loop BB12_3 Depth 3
	xorpd	%xmm2, %xmm2
	movl	$1, %edx
	movq	%rsi, %r8
.LBB12_2:                               # %.preheader.i
                                        #   Parent Loop BB12_1 Depth=1
                                        # =>  This Loop Header: Depth=2
                                        #       Child Loop BB12_3 Depth 3
	movl	$604, %r9d                      # imm = 0x25C
.LBB12_3:                               #   Parent Loop BB12_1 Depth=1
                                        #     Parent Loop BB12_2 Depth=2
                                        # =>    This Inner Loop Header: Depth=3
	movl	(%r8,%r9), %r10d
	xorl	%r11d, %r11d
	btl	%ecx, %r10d
	setb	%r11b
	xorps	%xmm3, %xmm3
	cvtsi2sd	%r11d, %xmm3
	addsd	%xmm3, %xmm3
	addsd	%xmm0, %xmm3
	addsd	%xmm3, %xmm2
	addq	$600, %r9                       # imm = 0x258
	cmpq	$89404, %r9                     # imm = 0x15D3C
	jne	.LBB12_3
# %bb.4:                                #   in Loop: Header=BB12_2 Depth=2
	incq	%rdx
	addq	$4, %r8
	cmpq	$149, %rdx
	jne	.LBB12_2
# %bb.5:                                # %_Z26measure_1bit_magnetizationPji.exit
                                        #   in Loop: Header=BB12_1 Depth=1
	divsd	%xmm1, %xmm2
	leaq	(%rcx,%rax), %rdx
	movsd	(%rdi,%rdx,8), %xmm3            # xmm3 = mem[0],zero
	addsd	%xmm2, %xmm3
	movsd	%xmm3, (%rdi,%rdx,8)
	mulsd	%xmm2, %xmm2
	addsd	768(%rdi,%rdx,8), %xmm2
	movsd	%xmm2, 768(%rdi,%rdx,8)
	incq	%rcx
	cmpq	$32, %rcx
	jne	.LBB12_1
# %bb.6:
	retq
.Lfunc_end12:
	.size	_Z28update_magnetization_trackerP11multiavg_trPji, .Lfunc_end12-_Z28update_magnetization_trackerP11multiavg_trPji
	.cfi_endproc
                                        # -- End function
	.section	.rodata.cst8,"aM",@progbits,8
	.p2align	3, 0x0                          # -- Begin function main
.LCPI13_0:
	.quad	0xc010000000000000              # double -4
.LCPI13_1:
	.quad	0xc020000000000000              # double -8
.LCPI13_2:
	.quad	0x4058000000000000              # double 96
.LCPI13_3:
	.quad	0x0000000000000000              # double 0
	.text
	.globl	main
	.type	main,@function
main:                                   # @main
	.cfi_startproc
# %bb.0:
	pushq	%rbp
	.cfi_def_cfa_offset 16
	pushq	%r15
	.cfi_def_cfa_offset 24
	pushq	%r14
	.cfi_def_cfa_offset 32
	pushq	%r13
	.cfi_def_cfa_offset 40
	pushq	%r12
	.cfi_def_cfa_offset 48
	pushq	%rbx
	.cfi_def_cfa_offset 56
	subq	$184712, %rsp                   # imm = 0x2D188
	.cfi_def_cfa_offset 184768
	.cfi_offset %rbx, -56
	.cfi_offset %r12, -48
	.cfi_offset %r13, -40
	.cfi_offset %r14, -32
	.cfi_offset %r15, -24
	.cfi_offset %rbp, -16
	movl	$.L.str.4, %edi
	movl	$.L.str.5, %esi
	callq	fopen
	movq	%rax, %rbx
	leaq	28(%rsp), %rcx
	leaq	32(%rsp), %r8
	leaq	40(%rsp), %r9
	leaq	44(%rsp), %r10
	leaq	48(%rsp), %r11
	leaq	52(%rsp), %r12
	subq	$8, %rsp
	.cfi_adjust_cfa_offset 8
	xorl	%r15d, %r15d
	leaq	32(%rsp), %r14
	movl	$.L.str.6, %esi
	movq	%rax, %rdi
	movq	%r14, %rdx
	xorl	%eax, %eax
	pushq	%r12
	.cfi_adjust_cfa_offset 8
	pushq	%r11
	.cfi_adjust_cfa_offset 8
	pushq	%r10
	.cfi_adjust_cfa_offset 8
	callq	__isoc23_fscanf
	addq	$32, %rsp
	.cfi_adjust_cfa_offset -32
	cvtss2sd	(%r14), %xmm0
	movl	$.L.str.7, %edi
	movb	$1, %al
	callq	printf
	xorps	%xmm0, %xmm0
	cvtss2sd	4(%r14), %xmm0
	movl	$.L.str.7, %edi
	movb	$1, %al
	callq	printf
	xorps	%xmm0, %xmm0
	cvtss2sd	8(%r14), %xmm0
	movl	$.L.str.7, %edi
	movb	$1, %al
	callq	printf
	movl	16(%r14), %esi
	movl	$.L.str.8, %edi
	xorl	%eax, %eax
	callq	printf
	movl	20(%r14), %esi
	movl	$.L.str.8, %edi
	xorl	%eax, %eax
	callq	printf
	movl	24(%r14), %esi
	movl	$.L.str.8, %edi
	xorl	%eax, %eax
	callq	printf
	movl	28(%r14), %esi
	movl	$.L.str.8, %edi
	xorl	%eax, %eax
	callq	printf
	movq	%rbx, %rdi
	callq	fclose
	movl	28(%r14), %edi
	callq	srand
	leaq	94704(%rsp), %rax
.LBB13_1:                               # %.preheader.i
                                        # =>This Loop Header: Depth=1
                                        #     Child Loop BB13_2 Depth 2
	xorl	%ecx, %ecx
.LBB13_2:                               #   Parent Loop BB13_1 Depth=1
                                        # =>  This Inner Loop Header: Depth=2
	movl	$0, (%rax,%rcx)
	addq	$600, %rcx                      # imm = 0x258
	cmpq	$90000, %rcx                    # imm = 0x15F90
	jne	.LBB13_2
# %bb.3:                                #   in Loop: Header=BB13_1 Depth=1
	incq	%r15
	addq	$4, %rax
	cmpq	$150, %r15
	jne	.LBB13_1
# %bb.4:                                # %_Z12init_t0_gridPj.exit
	xorps	%xmm0, %xmm0
	cvtss2sd	32(%rsp), %xmm0
	mulsd	.LCPI13_0(%rip), %xmm0
	cvtss2sd	24(%rsp), %xmm1
	divsd	%xmm1, %xmm0
	callq	exp
	xorps	%xmm1, %xmm1
	cvtss2sd	32(%rsp), %xmm1
	mulsd	.LCPI13_1(%rip), %xmm1
	movsd	%xmm0, 16(%rsp)                 # 8-byte Spill
	xorps	%xmm0, %xmm0
	cvtss2sd	24(%rsp), %xmm0
	divsd	%xmm0, %xmm1
	movapd	%xmm1, %xmm0
	callq	exp
	movsd	%xmm0, 8(%rsp)                  # 8-byte Spill
	movl	$.L.str.9, %edi
	movl	$.L.str.10, %esi
	callq	fopen
	movq	%rax, %rbx
	movl	$.L.str.11, %edi
	movl	$7, %esi
	movl	$1, %edx
	movq	%rax, %rcx
	callq	fwrite@PLT
	movl	$.L.str.12, %esi
	movq	%rbx, %rdi
	movl	$150, %edx
	movl	$32, %ecx
	xorl	%eax, %eax
	callq	fprintf
	xorps	%xmm0, %xmm0
	cvtss2sd	24(%rsp), %xmm0
	xorps	%xmm1, %xmm1
	cvtss2sd	28(%rsp), %xmm1
	cvtss2sd	32(%rsp), %xmm2
	movl	$.L.str.13, %esi
	movq	%rbx, %rdi
	movl	$3, %edx
	movb	$3, %al
	callq	fprintf
	movl	40(%rsp), %edx
	movl	44(%rsp), %ecx
	movl	48(%rsp), %r8d
	movl	52(%rsp), %r9d
	movl	$.L.str.14, %esi
	movq	%rbx, %rdi
	xorl	%eax, %eax
	callq	fprintf
	movl	$.L.str.15, %esi
	movq	%rbx, %rdi
	movl	$22500, %edx                    # imm = 0x57E4
	movl	$21904, %ecx                    # imm = 0x5590
	movl	$96, %r8d
	xorl	%eax, %eax
	callq	fprintf
	movl	40(%rsp), %eax
	subl	44(%rsp), %eax
	cltd
	idivl	48(%rsp)
	movl	%eax, %ebp
	xorps	%xmm0, %xmm0
	cvtsi2sd	%eax, %xmm0
	movsd	%xmm0, 56(%rsp)                 # 8-byte Spill
	leaq	3160(%rsp), %r14
	movl	$1536, %edx                     # imm = 0x600
	movq	%r14, %rdi
	xorl	%esi, %esi
	callq	memset@PLT
	movl	%ebp, 1536(%r14)
	leaq	4704(%rsp), %r15
	xorl	%r13d, %r13d
.LBB13_5:                               # =>This Loop Header: Depth=1
                                        #     Child Loop BB13_7 Depth 2
                                        #     Child Loop BB13_9 Depth 2
	movl	52(%rsp), %edi
	addl	%r13d, %edi
	callq	srand
	movl	$90000, %edx                    # imm = 0x15F90
	movq	%r15, %rdi
	leaq	94704(%rsp), %rsi
	callq	memcpy@PLT
	leal	1(%r13), %ebp
	movl	$.L.str.16, %edi
	movl	%ebp, %esi
	xorl	%eax, %eax
	callq	printf
	movl	44(%rsp), %esi
	movl	$.L.str.17, %edi
	xorl	%eax, %eax
	callq	printf
	movl	44(%rsp), %eax
	movl	$0, %r12d
	testl	%eax, %eax
	jle	.LBB13_8
# %bb.6:                                # %.lr.ph.preheader
                                        #   in Loop: Header=BB13_5 Depth=1
	xorl	%r12d, %r12d
.LBB13_7:                               # %.lr.ph
                                        #   Parent Loop BB13_5 Depth=1
                                        # =>  This Inner Loop Header: Depth=2
	movq	%r15, %rdi
	movsd	16(%rsp), %xmm0                 # 8-byte Reload
                                        # xmm0 = mem[0],zero
	movsd	8(%rsp), %xmm1                  # 8-byte Reload
                                        # xmm1 = mem[0],zero
	callq	_Z17update_grid_blackPjdd
	movq	%r15, %rdi
	movsd	16(%rsp), %xmm0                 # 8-byte Reload
                                        # xmm0 = mem[0],zero
	movsd	8(%rsp), %xmm1                  # 8-byte Reload
                                        # xmm1 = mem[0],zero
	callq	_Z17update_grid_whitePjdd
	incl	%r12d
	movl	44(%rsp), %eax
	cmpl	%eax, %r12d
	jl	.LBB13_7
.LBB13_8:                               # %._crit_edge
                                        #   in Loop: Header=BB13_5 Depth=1
	movl	40(%rsp), %esi
	subl	%eax, %esi
	movl	$.L.str.18, %edi
	movsd	56(%rsp), %xmm0                 # 8-byte Reload
                                        # xmm0 = mem[0],zero
	movb	$1, %al
	callq	printf
.LBB13_9:                               # %._crit_edge
                                        #   Parent Loop BB13_5 Depth=1
                                        # =>  This Inner Loop Header: Depth=2
	cmpl	40(%rsp), %r12d
	movsd	16(%rsp), %xmm0                 # 8-byte Reload
                                        # xmm0 = mem[0],zero
	movsd	8(%rsp), %xmm1                  # 8-byte Reload
                                        # xmm1 = mem[0],zero
	jge	.LBB13_13
# %bb.10:                               # %.lr.ph53
                                        #   in Loop: Header=BB13_9 Depth=2
	movq	%r15, %rdi
	callq	_Z17update_grid_blackPjdd
	movq	%r15, %rdi
	movsd	16(%rsp), %xmm0                 # 8-byte Reload
                                        # xmm0 = mem[0],zero
	movsd	8(%rsp), %xmm1                  # 8-byte Reload
                                        # xmm1 = mem[0],zero
	callq	_Z17update_grid_whitePjdd
	movl	%r12d, %eax
	cltd
	idivl	48(%rsp)
	testl	%edx, %edx
	jne	.LBB13_12
# %bb.11:                               #   in Loop: Header=BB13_9 Depth=2
	movq	%r14, %rdi
	movq	%r15, %rsi
	movl	%r13d, %edx
	callq	_Z28update_magnetization_trackerP11multiavg_trPji
.LBB13_12:                              #   in Loop: Header=BB13_9 Depth=2
	incl	%r12d
	jmp	.LBB13_9
.LBB13_13:                              # %._crit_edge54
                                        #   in Loop: Header=BB13_5 Depth=1
	movl	$.L.str.19, %edi
	movl	%ebp, %esi
	xorl	%eax, %eax
	callq	printf
	movl	%ebp, %r13d
	cmpl	$3, %ebp
	jne	.LBB13_5
# %bb.14:                               # %.preheader
	xorl	%r14d, %r14d
	leaq	1616(%rsp), %r15
	leaq	3160(%rsp), %r12
	leaq	72(%rsp), %r13
	xorps	%xmm2, %xmm2
	xorpd	%xmm0, %xmm0
.LBB13_15:                              # =>This Inner Loop Header: Depth=1
	movsd	%xmm0, 56(%rsp)                 # 8-byte Spill
	movsd	%xmm2, 8(%rsp)                  # 8-byte Spill
	movl	$1544, %edx                     # imm = 0x608
	movq	%r15, %rdi
	movq	%r12, %rsi
	callq	memcpy@PLT
	movsd	1616(%rsp,%r14,8), %xmm0        # xmm0 = mem[0],zero
	movsd	%xmm0, 16(%rsp)                 # 8-byte Spill
	xorps	%xmm0, %xmm0
	cvtsi2sdl	3152(%rsp), %xmm0
	movsd	%xmm0, 64(%rsp)                 # 8-byte Spill
	movl	$1544, %edx                     # imm = 0x608
	movq	%r13, %rdi
	movq	%r12, %rsi
	callq	memcpy@PLT
	xorps	%xmm1, %xmm1
	cvtsi2sdl	1608(%rsp), %xmm1
	movsd	840(%rsp,%r14,8), %xmm0         # xmm0 = mem[0],zero
	divsd	%xmm1, %xmm0
	movsd	72(%rsp,%r14,8), %xmm2          # xmm2 = mem[0],zero
	divsd	%xmm1, %xmm2
	mulsd	%xmm2, %xmm2
	subsd	%xmm2, %xmm0
	ucomisd	.LCPI13_3(%rip), %xmm0
	jb	.LBB13_21
# %bb.16:                               #   in Loop: Header=BB13_15 Depth=1
	xorps	%xmm1, %xmm1
	sqrtsd	%xmm0, %xmm1
	jmp	.LBB13_22
.LBB13_21:                              # %call.sqrt89
                                        #   in Loop: Header=BB13_15 Depth=1
	callq	sqrt
	movapd	%xmm0, %xmm1
.LBB13_22:                              # %.split88
                                        #   in Loop: Header=BB13_15 Depth=1
	movsd	16(%rsp), %xmm0                 # 8-byte Reload
                                        # xmm0 = mem[0],zero
	divsd	64(%rsp), %xmm0                 # 8-byte Folded Reload
	movsd	%xmm0, 16(%rsp)                 # 8-byte Spill
	incq	%r14
	movl	$.L.str.20, %esi
	movq	%rbx, %rdi
	movl	%r14d, %edx
	movb	$2, %al
	callq	fprintf
	movsd	8(%rsp), %xmm2                  # 8-byte Reload
                                        # xmm2 = mem[0],zero
	movsd	16(%rsp), %xmm0                 # 8-byte Reload
                                        # xmm0 = mem[0],zero
	addsd	%xmm0, %xmm2
	mulsd	%xmm0, %xmm0
	movapd	%xmm0, %xmm1
	movsd	56(%rsp), %xmm0                 # 8-byte Reload
                                        # xmm0 = mem[0],zero
	addsd	%xmm1, %xmm0
	cmpq	$96, %r14
	jne	.LBB13_15
# %bb.17:
	movsd	.LCPI13_2(%rip), %xmm1          # xmm1 = mem[0],zero
	divsd	%xmm1, %xmm2
	divsd	%xmm1, %xmm0
	movapd	%xmm2, %xmm1
	mulsd	%xmm2, %xmm1
	subsd	%xmm1, %xmm0
	xorpd	%xmm1, %xmm1
	ucomisd	%xmm1, %xmm0
	jb	.LBB13_19
# %bb.18:
	xorps	%xmm1, %xmm1
	sqrtsd	%xmm0, %xmm1
	jmp	.LBB13_20
.LBB13_19:                              # %call.sqrt
	movsd	%xmm2, 8(%rsp)                  # 8-byte Spill
	callq	sqrt
	movsd	8(%rsp), %xmm2                  # 8-byte Reload
                                        # xmm2 = mem[0],zero
	movapd	%xmm0, %xmm1
.LBB13_20:                              # %.split
	movl	$.L.str.21, %esi
	movq	%rbx, %rdi
	movapd	%xmm2, %xmm0
	movb	$2, %al
	callq	fprintf
	leaq	4704(%rsp), %rdi
	callq	_Z15multidump_a_fewPj
	xorl	%eax, %eax
	addq	$184712, %rsp                   # imm = 0x2D188
	.cfi_def_cfa_offset 56
	popq	%rbx
	.cfi_def_cfa_offset 48
	popq	%r12
	.cfi_def_cfa_offset 40
	popq	%r13
	.cfi_def_cfa_offset 32
	popq	%r14
	.cfi_def_cfa_offset 24
	popq	%r15
	.cfi_def_cfa_offset 16
	popq	%rbp
	.cfi_def_cfa_offset 8
	retq
.Lfunc_end13:
	.size	main, .Lfunc_end13-main
	.cfi_endproc
                                        # -- End function
	.type	.L.str.1,@object                # @.str.1
	.section	.rodata.str1.1,"aMS",@progbits,1
.L.str.1:
	.asciz	"\342\226\210"
	.size	.L.str.1, 4

	.type	.L.str.3,@object                # @.str.3
.L.str.3:
	.asciz	"grid on bit %i (out of %i):\n"
	.size	.L.str.3, 29

	.type	.L.str.4,@object                # @.str.4
.L.str.4:
	.asciz	"params.txt"
	.size	.L.str.4, 11

	.type	.L.str.5,@object                # @.str.5
.L.str.5:
	.asciz	"r"
	.size	.L.str.5, 2

	.type	.L.str.6,@object                # @.str.6
.L.str.6:
	.asciz	"temperature %f\ntemperature_start %f\ncoupling %f\nsimulation_t_max %i\nthermalization_time %i\ntime_between_measurements %i\nbase_random_seed %i\n"
	.size	.L.str.6, 141

	.type	.L.str.7,@object                # @.str.7
.L.str.7:
	.asciz	"%f\n"
	.size	.L.str.7, 4

	.type	.L.str.8,@object                # @.str.8
.L.str.8:
	.asciz	"%i\n"
	.size	.L.str.8, 4

	.type	.L.str.9,@object                # @.str.9
.L.str.9:
	.asciz	"results.txt"
	.size	.L.str.9, 12

	.type	.L.str.10,@object               # @.str.10
.L.str.10:
	.asciz	"w"
	.size	.L.str.10, 2

	.type	.L.str.11,@object               # @.str.11
.L.str.11:
	.asciz	"# cpu2\n"
	.size	.L.str.11, 8

	.type	.L.str.12,@object               # @.str.12
.L.str.12:
	.asciz	"# hard-coded parameters:\n# linear_size: %i\n# spin_coding_size: %i\n"
	.size	.L.str.12, 67

	.type	.L.str.13,@object               # @.str.13
.L.str.13:
	.asciz	"# parameters:\n# temperature: %f\n#temp_start: %f\n# coupling: %f\n# repetitions: %i\n"
	.size	.L.str.13, 82

	.type	.L.str.14,@object               # @.str.14
.L.str.14:
	.asciz	"# simulation_t_max: %i\n# thermalization_time: %i\n# time_between_measurements: %i\n# base_random_seed: %i\n"
	.size	.L.str.14, 105

	.type	.L.str.15,@object               # @.str.15
.L.str.15:
	.asciz	"# extra:\n# area: %i\n# active_spins_excluding_boundaries:%i\n# total_independent_sims: %i\n"
	.size	.L.str.15, 89

	.type	.L.str.16,@object               # @.str.16
.L.str.16:
	.asciz	"# simulation %i\n"
	.size	.L.str.16, 17

	.type	.L.str.17,@object               # @.str.17
.L.str.17:
	.asciz	"#    waiting thermalization for the first %i sim steps.\n"
	.size	.L.str.17, 57

	.type	.L.str.18,@object               # @.str.18
.L.str.18:
	.asciz	"#    finished thermalization. running %i more simulation steps and performing %f measures.\n"
	.size	.L.str.18, 92

	.type	.L.str.19,@object               # @.str.19
.L.str.19:
	.asciz	"# end simulation %i\n"
	.size	.L.str.19, 21

	.type	.L.str.20,@object               # @.str.20
.L.str.20:
	.asciz	"# average of simulation %i\n: %f +- %f\n"
	.size	.L.str.20, 39

	.type	.L.str.21,@object               # @.str.21
.L.str.21:
	.asciz	"# overall average \n: %f +- %f\n"
	.size	.L.str.21, 31

	.type	__hip_cuid_,@object             # @__hip_cuid_
	.bss
	.globl	__hip_cuid_
__hip_cuid_:
	.byte	0                               # 0x0
	.size	__hip_cuid_, 1

	.ident	"AMD clang version 18.0.0git (https://github.com/RadeonOpenCompute/llvm-project roc-6.3.2 25012 e5bf7e55c91490b07c49d8960fa7983d864936c4)"
	.section	".note.GNU-stack","",@progbits
	.addrsig
	.addrsig_sym __hip_cuid_

	.text
	.p2alignl 7, 3214868480
	.fill 96, 4, 3214868480
	.type	__hip_cuid_,@object             ; @__hip_cuid_
	.section	.bss,"aw",@nobits
	.globl	__hip_cuid_
__hip_cuid_:
	.byte	0                               ; 0x0
	.size	__hip_cuid_, 1

	.ident	"AMD clang version 18.0.0git (https://github.com/RadeonOpenCompute/llvm-project roc-6.3.2 25012 e5bf7e55c91490b07c49d8960fa7983d864936c4)"
	.section	".note.GNU-stack","",@progbits
	.addrsig
	.addrsig_sym __hip_cuid_
	.amdgcn_target "amdgcn-amd-amdhsa--gfx1100"
	.amdgpu_metadata
---
amdhsa.kernels:  []
amdhsa.target:   amdgcn-amd-amdhsa--gfx1100
amdhsa.version:
  - 1
  - 2
...

	.end_amdgpu_metadata
