Problem 595

Incremental Random Sort S(52) expected shuffles, rounded to 8 decimals (f64 DP).

Answer54.17529329
Output54.17529329
StatusPASS
Native helperno
Runtime0 ms
Peak memory1088 KB
Time complexityO(n^2) (estimated)
Space complexityO(n) (estimated)

Performance comparison

MetricOur solutionBest known
Time complexityO(n^2)O(n * s^2)
Space complexityO(n)O(s^2)
ApproachFlow solutionMarkov chain or DP over states
VerdictUnknown

Flow source

# Project Euler 595
# Incremental Random Sort
# S(52) expected shuffles, rounded to 8 decimals (f64 DP).

extern {
    function calloc(n: i64, size: i64) -> ptr<void>
    function free(p: ptr<void>) -> void
    function floor(x: f64) -> f64
}

function expected_shuffles(n: i64) -> f64 {
    let fact: ptr<f64> = calloc(n + 1, 8)
    if fact == null { return -1.0 }
    fact[0] = 1.0
    fact[1] = 1.0
    let mut i: i64 = 2
    while i <= n {
        fact[i] = fact[i - 1] * (i as f64)
        i = i + 1
    }

    # a[m*(n) + r] succession counts; store rows packed with stride n
    let a: ptr<f64> = calloc((n + 1) * n, 8)
    if a == null { free(fact); return -1.0 }
    a[1 * n + 0] = 1.0

    let mut m: i64 = 2
    while m <= n {
        let mut r: i64 = 0
        while r < m {
            # C(m-1, r)
            let mut c1: f64 = 1.0
            let mut t: i64 = 0
            let mut kk: i64 = r
            if kk > m - 1 - kk { kk = m - 1 - kk }
            t = 1
            while t <= kk {
                c1 = c1 * ((m - 1 - kk + t) as f64) / (t as f64)
                t = t + 1
            }
            let mut s: f64 = 0.0
            let mut j: i64 = 0
            while j < m - r {
                let k: i64 = m - r - j
                # C(m-1-r, j) * k!
                let mut cj: f64 = 1.0
                let mut jj: i64 = j
                if jj > m - 1 - r - jj { jj = m - 1 - r - jj }
                t = 1
                while t <= jj {
                    cj = cj * ((m - 1 - r - jj + t) as f64) / (t as f64)
                    t = t + 1
                }
                let term: f64 = cj * fact[k]
                if (j & 1) != 0 {
                    s = s - term
                } else {
                    s = s + term
                }
                j = j + 1
            }
            a[m * n + r] = c1 * s
            r = r + 1
        }
        m = m + 1
    }

    let T: ptr<f64> = calloc(n + 1, 8)
    if T == null { free(a); free(fact); return -1.0 }
    T[1] = 0.0
    m = 2
    while m <= n {
        let denom: f64 = fact[m] - a[m * n + 0]
        let mut num: f64 = fact[m]
        let mut r: i64 = 1
        while r < m {
            num = num + a[m * n + r] * T[m - r]
            r = r + 1
        }
        T[m] = num / denom
        m = m + 1
    }

    let mut Sn: f64 = 0.0
    let mut r: i64 = 0
    while r < n {
        Sn = Sn + (a[n * n + r] / fact[n]) * T[n - r]
        r = r + 1
    }
    free(T)
    free(a)
    free(fact)
    return Sn
}

function main() -> i32 {
    let s: f64 = expected_shuffles(52)
    # round half-up to 8 decimals
    let scaled: f64 = s * 100000000.0
    let mut q: i64 = floor(scaled) as i64
    let frac: f64 = scaled - (q as f64)
    if frac >= 0.5 {
        q = q + 1
    }
    let ip: i64 = q / 100000000
    let fp: i64 = q % 100000000
    printf("%lld.%08lld\n", ip, fp)
    return 0
}

Generated C

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Flow runtime helpers */
typedef struct flow_temp_node { struct flow_temp_node* next; } flow_temp_node;
static flow_temp_node* flow_temp_head = NULL;
static int flow_temp_atexit_set = 0;
__attribute__((unused)) static void flow_temp_free_all(void) {
    while (flow_temp_head) {
        flow_temp_node* n = flow_temp_head;
        flow_temp_head = n->next;
        free(n);
    }
}
__attribute__((unused)) static void* flow_temp_alloc(size_t nbytes) {
    flow_temp_node* node = (flow_temp_node*)malloc(sizeof(flow_temp_node) + nbytes);
    if (!node) return NULL;
    node->next = flow_temp_head;
    flow_temp_head = node;
    if (!flow_temp_atexit_set) {
        flow_temp_atexit_set = 1;
        atexit(flow_temp_free_all);
    }
    return (void*)(node + 1);
}
#ifndef FLOW_DIAG
#define FLOW_DIAG(msg) fprintf(stderr, "%s", (msg))
#endif
#ifndef FLOW_LOG
#define FLOW_LOG(fmt, ...) printf(fmt, __VA_ARGS__)
#endif
#ifndef FLOW_LOG_EMPTY
#define FLOW_LOG_EMPTY(fmt) printf(fmt)
#endif
static char* flow_strcat(const char* a, const char* b) {
    size_t la = strlen(a ? a : ""), lb = strlen(b ? b : "");
    char* r = (char*)flow_temp_alloc(la + lb + 1);
    if (!r) return NULL;
    if (la) memcpy(r, a, la);
    if (lb) memcpy(r + la, b, lb);
    r[la + lb] = '\0';
    return r;
}

#define __flow_in_arr(arr, val) __extension__ ({ \
    int _found = 0; \
    size_t _n = sizeof(arr)/sizeof((arr)[0]); \
    for (size_t _i = 0; _i < _n; _i++) { \
        if ((arr)[_i] == (val)) { _found = 1; break; } \
    } _found; })

/* Unified fault handler (MISRA #279) — override with -DFLOW_FAULT_HANDLER=fn */
#ifndef FLOW_FAULT_HANDLER
__attribute__((unused)) static inline void flow_fault_handler(const char* msg) {
    fprintf(stderr, "flow: %s\n", msg ? msg : "fault");
    abort();
#if defined(__GNUC__) || defined(__clang__)
    __builtin_unreachable();
#endif
}
#else
#define flow_fault_handler FLOW_FAULT_HANDLER
#endif
#define flow_div_by_zero_handler() flow_fault_handler("division by zero")
#define flow_shift_ub_handler() flow_fault_handler("invalid shift (amount out of range or left-shift of negative)")

#ifndef FLOW_CHECKED_DIV
#define FLOW_CHECKED_DIV(L, R) (((R) != 0) ? ((L) / (R)) : (flow_div_by_zero_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_MOD
#define FLOW_CHECKED_MOD(L, R) (((R) != 0) ? ((L) % (R)) : (flow_div_by_zero_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_SHL
#define FLOW_CHECKED_SHL(L, R) ((((R) >= 0) && ((unsigned long long)(R) < (sizeof(L) * 8ull)) && ((L) >= 0)) ? ((L) << (R)) : (flow_shift_ub_handler(), (L) * 0))
#endif
#ifndef FLOW_CHECKED_SHR
#define FLOW_CHECKED_SHR(L, R) ((((R) >= 0) && ((unsigned long long)(R) < (sizeof(L) * 8ull))) ? ((L) >> (R)) : (flow_shift_ub_handler(), (L) * 0))
#endif

#include <math.h>

void* _ui_state = NULL;

static inline float i32_to_f32(int32_t v) { return (float)v; }

/* Host stub for @gpu kernels (device codegen replaces this). */
static inline int32_t gpu_thread_id(void) { return 0; }

double expected_shuffles_i64(int64_t n);
int32_t main(void);




double expected_shuffles_i64(int64_t n) {
    double* fact = (double*)(calloc((n + 1), 8));
    if (fact == NULL) {
        return (-1.0);
    }
    fact[0] = 1.0;
    fact[1] = 1.0;
    int64_t i = 2;
    while (i <= n) {
        fact[i] = (fact[(i - 1)] * ((double)(i)));
        i = (i + 1);
    }
    double* a = (double*)(calloc(((n + 1) * n), 8));
    if (a == NULL) {
        free(fact);
        return (-1.0);
    }
    a[((1 * n) + 0)] = 1.0;
    int64_t m = 2;
    while (m <= n) {
        int64_t r = 0;
        while (r < m) {
            double c1 = 1.0;
            int64_t t = 0;
            int64_t kk = r;
            if (kk > ((m - 1) - kk)) {
                kk = ((m - 1) - kk);
            }
            t = 1;
            while (t <= kk) {
                c1 = ((c1 * ((double)((((m - 1) - kk) + t)))) / ((double)(t)));
                t = (t + 1);
            }
            double s = 0.0;
            int64_t j = 0;
            while (j < (m - r)) {
                int64_t k = ((m - r) - j);
                double cj = 1.0;
                int64_t jj = j;
                if (jj > (((m - 1) - r) - jj)) {
                    jj = (((m - 1) - r) - jj);
                }
                t = 1;
                while (t <= jj) {
                    cj = ((cj * ((double)(((((m - 1) - r) - jj) + t)))) / ((double)(t)));
                    t = (t + 1);
                }
                double term = (cj * fact[k]);
                if ((j & 1) != 0) {
                    s = (s - term);
                } else {
                    s = (s + term);
                }
                j = (j + 1);
            }
            a[((m * n) + r)] = (c1 * s);
            r = (r + 1);
        }
        m = (m + 1);
    }
    double* T = (double*)(calloc((n + 1), 8));
    if (T == NULL) {
        free(a);
        free(fact);
        return (-1.0);
    }
    T[1] = 0.0;
    m = 2;
    while (m <= n) {
        double denom = (fact[m] - a[((m * n) + 0)]);
        double num = fact[m];
        int64_t r = 1;
        while (r < m) {
            num = (num + (a[((m * n) + r)] * T[(m - r)]));
            r = (r + 1);
        }
        T[m] = (num / denom);
        m = (m + 1);
    }
    double Sn = 0.0;
    int64_t r = 0;
    while (r < n) {
        Sn = (Sn + ((a[((n * n) + r)] / fact[n]) * T[(n - r)]));
        r = (r + 1);
    }
    free(T);
    free(a);
    free(fact);
    return Sn;
}

int32_t main(void) {
    double s = expected_shuffles_i64(52);
    double scaled = (s * 100000000.0);
    int64_t q = ((int64_t)(floor(scaled)));
    double frac = (scaled - ((double)(q)));
    if (frac >= 0.5) {
        q = (q + 1);
    }
    int64_t ip = FLOW_CHECKED_DIV((q), (100000000));
    int64_t fp = FLOW_CHECKED_MOD((q), (100000000));
    printf("%lld.%08lld\n", ip, fp);
    return 0;
}

Generated MLIR

module {
  llvm.func @printf(!llvm.ptr, ...) -> i32
  llvm.mlir.global internal constant @str_0("%lld.%08lld\n\00") {addr_space = 0 : i32} : !llvm.array<13 x i8>
  func.func private @calloc(i64, i64) -> !llvm.ptr
  func.func private @free(!llvm.ptr) -> ()
  func.func private @floor(f64) -> f64
  func.func @expected_shuffles(%arg0: i64) -> f64 {
    %1 = arith.constant 1 : i32
    %3 = arith.extsi %1 : i32 to i64
    %2 = arith.addi %arg0, %3 : i64
    %4 = arith.constant 8 : i32
    %5 = arith.extsi %4 : i32 to i64
    %0 = func.call @calloc(%2, %5) : (i64, i64) -> !llvm.ptr
    %6 = llvm.mlir.zero : !llvm.ptr
    %7 = llvm.icmp "eq" %0, %6 : !llvm.ptr
    cf.cond_br %7, ^bb0, ^bb1
    ^bb0:
      %8 = arith.constant 1.0 : f32
      %9 = arith.negf %8 : f32
      %10 = arith.extf %9 : f32 to f64
      func.return %10 : f64
    ^bb1:
      cf.br ^bb2
    ^bb2:
    %11 = arith.constant 1.0 : f32
    %12 = arith.constant 0 : i32
    %13 = arith.extf %11 : f32 to f64
    %14 = arith.extsi %12 : i32 to i64
    %15 = llvm.getelementptr %0[%14] : (!llvm.ptr, i64) -> !llvm.ptr, f64
    llvm.store %13, %15 : f64, !llvm.ptr
    %16 = arith.constant 1.0 : f32
    %17 = arith.constant 1 : i32
    %18 = arith.extf %16 : f32 to f64
    %19 = arith.extsi %17 : i32 to i64
    %20 = llvm.getelementptr %0[%19] : (!llvm.ptr, i64) -> !llvm.ptr, f64
    llvm.store %18, %20 : f64, !llvm.ptr
    %21 = arith.constant 2 : i32
    %22 = arith.extsi %21 : i32 to i64
    %23 = llvm.mlir.constant(1 : i64) : i64
    %24 = llvm.alloca %23 x i64 : (i64) -> !llvm.ptr
    llvm.store %22, %24 : i64, !llvm.ptr
    cf.br ^bb3
    ^bb3:
    %25 = llvm.load %24 : !llvm.ptr -> i64
    %26 = arith.cmpi sle, %25, %arg0 : i64
    cf.cond_br %26, ^bb4, ^bb5
    ^bb4:
      %28 = llvm.load %24 : !llvm.ptr -> i64
      %29 = arith.constant 1 : i32
      %31 = arith.extsi %29 : i32 to i64
      %30 = arith.subi %28, %31 : i64
      %32 = llvm.getelementptr %0[%30] : (!llvm.ptr, i64) -> !llvm.ptr, f64
      %27 = llvm.load %32 : !llvm.ptr -> f64
      %33 = llvm.load %24 : !llvm.ptr -> i64
      %34 = arith.sitofp %33 : i64 to f64
      %35 = arith.mulf %27, %34 : f64
      %36 = llvm.load %24 : !llvm.ptr -> i64
      %37 = llvm.getelementptr %0[%36] : (!llvm.ptr, i64) -> !llvm.ptr, f64
      llvm.store %35, %37 : f64, !llvm.ptr
      %38 = llvm.load %24 : !llvm.ptr -> i64
      %39 = arith.constant 1 : i32
      %41 = arith.extsi %39 : i32 to i64
      %40 = arith.addi %38, %41 : i64
      llvm.store %40, %24 : i64, !llvm.ptr
      cf.br ^bb3
    ^bb5:
    %43 = arith.constant 1 : i32
    %45 = arith.extsi %43 : i32 to i64
    %44 = arith.addi %arg0, %45 : i64
    %46 = arith.muli %44, %arg0 : i64
    %47 = arith.constant 8 : i32
    %48 = arith.extsi %47 : i32 to i64
    %42 = func.call @calloc(%46, %48) : (i64, i64) -> !llvm.ptr
    %49 = llvm.mlir.zero : !llvm.ptr
    %50 = llvm.icmp "eq" %42, %49 : !llvm.ptr
    cf.cond_br %50, ^bb6, ^bb7
    ^bb6:
      func.call @free(%0) : (!llvm.ptr) -> ()
      %52 = arith.constant 1.0 : f32
      %53 = arith.negf %52 : f32
      %54 = arith.extf %53 : f32 to f64
      func.return %54 : f64
    ^bb7:
      cf.br ^bb8
    ^bb8:
    %55 = arith.constant 1.0 : f32
    %56 = arith.constant 1 : i32
    %58 = arith.extsi %56 : i32 to i64
    %57 = arith.muli %58, %arg0 : i64
    %59 = arith.constant 0 : i32
    %61 = arith.extsi %59 : i32 to i64
    %60 = arith.addi %57, %61 : i64
    %62 = arith.extf %55 : f32 to f64
    %63 = llvm.getelementptr %42[%60] : (!llvm.ptr, i64) -> !llvm.ptr, f64
    llvm.store %62, %63 : f64, !llvm.ptr
    %64 = arith.constant 2 : i32
    %65 = arith.extsi %64 : i32 to i64
    %66 = llvm.mlir.constant(1 : i64) : i64
    %67 = llvm.alloca %66 x i64 : (i64) -> !llvm.ptr
    llvm.store %65, %67 : i64, !llvm.ptr
    cf.br ^bb9
    ^bb9:
    %68 = llvm.load %67 : !llvm.ptr -> i64
    %69 = arith.cmpi sle, %68, %arg0 : i64
    cf.cond_br %69, ^bb10, ^bb11
    ^bb10:
      %70 = arith.constant 0 : i32
      %71 = arith.extsi %70 : i32 to i64
      %72 = llvm.mlir.constant(1 : i64) : i64
      %73 = llvm.alloca %72 x i64 : (i64) -> !llvm.ptr
      llvm.store %71, %73 : i64, !llvm.ptr
      cf.br ^bb12
      ^bb12:
      %74 = llvm.load %73 : !llvm.ptr -> i64
      %75 = llvm.load %67 : !llvm.ptr -> i64
      %76 = arith.cmpi slt, %74, %75 : i64
      cf.cond_br %76, ^bb13, ^bb14
      ^bb13:
        %77 = arith.constant 1.0 : f32
        %78 = arith.extf %77 : f32 to f64
        %79 = llvm.mlir.constant(1 : i64) : i64
        %80 = llvm.alloca %79 x f64 : (i64) -> !llvm.ptr
        llvm.store %78, %80 : f64, !llvm.ptr
        %81 = arith.constant 0 : i32
        %82 = arith.extsi %81 : i32 to i64
        %83 = llvm.mlir.constant(1 : i64) : i64
        %84 = llvm.alloca %83 x i64 : (i64) -> !llvm.ptr
        llvm.store %82, %84 : i64, !llvm.ptr
        %85 = llvm.load %73 : !llvm.ptr -> i64
        %86 = llvm.mlir.constant(1 : i64) : i64
        %87 = llvm.alloca %86 x i64 : (i64) -> !llvm.ptr
        llvm.store %85, %87 : i64, !llvm.ptr
        %88 = llvm.load %87 : !llvm.ptr -> i64
        %89 = llvm.load %67 : !llvm.ptr -> i64
        %90 = arith.constant 1 : i32
        %92 = arith.extsi %90 : i32 to i64
        %91 = arith.subi %89, %92 : i64
        %93 = llvm.load %87 : !llvm.ptr -> i64
        %94 = arith.subi %91, %93 : i64
        %95 = arith.cmpi sgt, %88, %94 : i64
        cf.cond_br %95, ^bb15, ^bb16
        ^bb15:
          %96 = llvm.load %67 : !llvm.ptr -> i64
          %97 = arith.constant 1 : i32
          %99 = arith.extsi %97 : i32 to i64
          %98 = arith.subi %96, %99 : i64
          %100 = llvm.load %87 : !llvm.ptr -> i64
          %101 = arith.subi %98, %100 : i64
          llvm.store %101, %87 : i64, !llvm.ptr
          cf.br ^bb17
        ^bb16:
          cf.br ^bb17
        ^bb17:
        %102 = arith.constant 1 : i32
        %103 = arith.extsi %102 : i32 to i64
        llvm.store %103, %84 : i64, !llvm.ptr
        cf.br ^bb18
        ^bb18:
        %104 = llvm.load %84 : !llvm.ptr -> i64
        %105 = llvm.load %87 : !llvm.ptr -> i64
        %106 = arith.cmpi sle, %104, %105 : i64
        cf.cond_br %106, ^bb19, ^bb20
        ^bb19:
          %107 = llvm.load %80 : !llvm.ptr -> f64
          %108 = llvm.load %67 : !llvm.ptr -> i64
          %109 = arith.constant 1 : i32
          %111 = arith.extsi %109 : i32 to i64
          %110 = arith.subi %108, %111 : i64
          %112 = llvm.load %87 : !llvm.ptr -> i64
          %113 = arith.subi %110, %112 : i64
          %114 = llvm.load %84 : !llvm.ptr -> i64
          %115 = arith.addi %113, %114 : i64
          %116 = arith.sitofp %115 : i64 to f64
          %117 = arith.mulf %107, %116 : f64
          %118 = llvm.load %84 : !llvm.ptr -> i64
          %119 = arith.sitofp %118 : i64 to f64
          %120 = arith.divf %117, %119 : f64
          llvm.store %120, %80 : f64, !llvm.ptr
          %121 = llvm.load %84 : !llvm.ptr -> i64
          %122 = arith.constant 1 : i32
          %124 = arith.extsi %122 : i32 to i64
          %123 = arith.addi %121, %124 : i64
          llvm.store %123, %84 : i64, !llvm.ptr
          cf.br ^bb18
        ^bb20:
        %125 = arith.constant 0.0 : f32
        %126 = arith.extf %125 : f32 to f64
        %127 = llvm.mlir.constant(1 : i64) : i64
        %128 = llvm.alloca %127 x f64 : (i64) -> !llvm.ptr
        llvm.store %126, %128 : f64, !llvm.ptr
        %129 = arith.constant 0 : i32
        %130 = arith.extsi %129 : i32 to i64
        %131 = llvm.mlir.constant(1 : i64) : i64
        %132 = llvm.alloca %131 x i64 : (i64) -> !llvm.ptr
        llvm.store %130, %132 : i64, !llvm.ptr
        cf.br ^bb21
        ^bb21:
        %133 = llvm.load %132 : !llvm.ptr -> i64
        %134 = llvm.load %67 : !llvm.ptr -> i64
        %135 = llvm.load %73 : !llvm.ptr -> i64
        %136 = arith.subi %134, %135 : i64
        %137 = arith.cmpi slt, %133, %136 : i64
        cf.cond_br %137, ^bb22, ^bb23
        ^bb22:
          %138 = llvm.load %67 : !llvm.ptr -> i64
          %139 = llvm.load %73 : !llvm.ptr -> i64
          %140 = arith.subi %138, %139 : i64
          %141 = llvm.load %132 : !llvm.ptr -> i64
          %142 = arith.subi %140, %141 : i64
          %143 = arith.constant 1.0 : f32
          %144 = arith.extf %143 : f32 to f64
          %145 = llvm.mlir.constant(1 : i64) : i64
          %146 = llvm.alloca %145 x f64 : (i64) -> !llvm.ptr
          llvm.store %144, %146 : f64, !llvm.ptr
          %147 = llvm.load %132 : !llvm.ptr -> i64
          %148 = llvm.mlir.constant(1 : i64) : i64
          %149 = llvm.alloca %148 x i64 : (i64) -> !llvm.ptr
          llvm.store %147, %149 : i64, !llvm.ptr
          %150 = llvm.load %149 : !llvm.ptr -> i64
          %151 = llvm.load %67 : !llvm.ptr -> i64
          %152 = arith.constant 1 : i32
          %154 = arith.extsi %152 : i32 to i64
          %153 = arith.subi %151, %154 : i64
          %155 = llvm.load %73 : !llvm.ptr -> i64
          %156 = arith.subi %153, %155 : i64
          %157 = llvm.load %149 : !llvm.ptr -> i64
          %158 = arith.subi %156, %157 : i64
          %159 = arith.cmpi sgt, %150, %158 : i64
          cf.cond_br %159, ^bb24, ^bb25
          ^bb24:
            %160 = llvm.load %67 : !llvm.ptr -> i64
            %161 = arith.constant 1 : i32
            %163 = arith.extsi %161 : i32 to i64
            %162 = arith.subi %160, %163 : i64
            %164 = llvm.load %73 : !llvm.ptr -> i64
            %165 = arith.subi %162, %164 : i64
            %166 = llvm.load %149 : !llvm.ptr -> i64
            %167 = arith.subi %165, %166 : i64
            llvm.store %167, %149 : i64, !llvm.ptr
            cf.br ^bb26
          ^bb25:
            cf.br ^bb26
          ^bb26:
          %168 = arith.constant 1 : i32
          %169 = arith.extsi %168 : i32 to i64
          llvm.store %169, %84 : i64, !llvm.ptr
          cf.br ^bb27
          ^bb27:
          %170 = llvm.load %84 : !llvm.ptr -> i64
          %171 = llvm.load %149 : !llvm.ptr -> i64
          %172 = arith.cmpi sle, %170, %171 : i64
          cf.cond_br %172, ^bb28, ^bb29
          ^bb28:
            %173 = llvm.load %146 : !llvm.ptr -> f64
            %174 = llvm.load %67 : !llvm.ptr -> i64
            %175 = arith.constant 1 : i32
            %177 = arith.extsi %175 : i32 to i64
            %176 = arith.subi %174, %177 : i64
            %178 = llvm.load %73 : !llvm.ptr -> i64
            %179 = arith.subi %176, %178 : i64
            %180 = llvm.load %149 : !llvm.ptr -> i64
            %181 = arith.subi %179, %180 : i64
            %182 = llvm.load %84 : !llvm.ptr -> i64
            %183 = arith.addi %181, %182 : i64
            %184 = arith.sitofp %183 : i64 to f64
            %185 = arith.mulf %173, %184 : f64
            %186 = llvm.load %84 : !llvm.ptr -> i64
            %187 = arith.sitofp %186 : i64 to f64
            %188 = arith.divf %185, %187 : f64
            llvm.store %188, %146 : f64, !llvm.ptr
            %189 = llvm.load %84 : !llvm.ptr -> i64
            %190 = arith.constant 1 : i32
            %192 = arith.extsi %190 : i32 to i64
            %191 = arith.addi %189, %192 : i64
            llvm.store %191, %84 : i64, !llvm.ptr
            cf.br ^bb27
          ^bb29:
          %193 = llvm.load %146 : !llvm.ptr -> f64
          %195 = llvm.getelementptr %0[%142] : (!llvm.ptr, i64) -> !llvm.ptr, f64
          %194 = llvm.load %195 : !llvm.ptr -> f64
          %196 = arith.mulf %193, %194 : f64
          %197 = llvm.load %132 : !llvm.ptr -> i64
          %198 = arith.constant 1 : i32
          %200 = arith.extsi %198 : i32 to i64
          %199 = arith.andi %197, %200 : i64
          %201 = arith.constant 0 : i32
          %203 = arith.extsi %201 : i32 to i64
          %202 = arith.cmpi ne, %199, %203 : i64
          cf.cond_br %202, ^bb30, ^bb31
          ^bb30:
            %204 = llvm.load %128 : !llvm.ptr -> f64
            %205 = arith.subf %204, %196 : f64
            llvm.store %205, %128 : f64, !llvm.ptr
            cf.br ^bb32
          ^bb31:
            %206 = llvm.load %128 : !llvm.ptr -> f64
            %207 = arith.addf %206, %196 : f64
            llvm.store %207, %128 : f64, !llvm.ptr
            cf.br ^bb32
          ^bb32:
          %208 = llvm.load %132 : !llvm.ptr -> i64
          %209 = arith.constant 1 : i32
          %211 = arith.extsi %209 : i32 to i64
          %210 = arith.addi %208, %211 : i64
          llvm.store %210, %132 : i64, !llvm.ptr
          cf.br ^bb21
        ^bb23:
        %212 = llvm.load %80 : !llvm.ptr -> f64
        %213 = llvm.load %128 : !llvm.ptr -> f64
        %214 = arith.mulf %212, %213 : f64
        %215 = llvm.load %67 : !llvm.ptr -> i64
        %216 = arith.muli %215, %arg0 : i64
        %217 = llvm.load %73 : !llvm.ptr -> i64
        %218 = arith.addi %216, %217 : i64
        %219 = llvm.getelementptr %42[%218] : (!llvm.ptr, i64) -> !llvm.ptr, f64
        llvm.store %214, %219 : f64, !llvm.ptr
        %220 = llvm.load %73 : !llvm.ptr -> i64
        %221 = arith.constant 1 : i32
        %223 = arith.extsi %221 : i32 to i64
        %222 = arith.addi %220, %223 : i64
        llvm.store %222, %73 : i64, !llvm.ptr
        cf.br ^bb12
      ^bb14:
      %224 = llvm.load %67 : !llvm.ptr -> i64
      %225 = arith.constant 1 : i32
      %227 = arith.extsi %225 : i32 to i64
      %226 = arith.addi %224, %227 : i64
      llvm.store %226, %67 : i64, !llvm.ptr
      cf.br ^bb9
    ^bb11:
    %229 = arith.constant 1 : i32
    %231 = arith.extsi %229 : i32 to i64
    %230 = arith.addi %arg0, %231 : i64
    %232 = arith.constant 8 : i32
    %233 = arith.extsi %232 : i32 to i64
    %228 = func.call @calloc(%230, %233) : (i64, i64) -> !llvm.ptr
    %234 = llvm.mlir.zero : !llvm.ptr
    %235 = llvm.icmp "eq" %228, %234 : !llvm.ptr
    cf.cond_br %235, ^bb33, ^bb34
    ^bb33:
      func.call @free(%42) : (!llvm.ptr) -> ()
      func.call @free(%0) : (!llvm.ptr) -> ()
      %238 = arith.constant 1.0 : f32
      %239 = arith.negf %238 : f32
      %240 = arith.extf %239 : f32 to f64
      func.return %240 : f64
    ^bb34:
      cf.br ^bb35
    ^bb35:
    %241 = arith.constant 0.0 : f32
    %242 = arith.constant 1 : i32
    %243 = arith.extf %241 : f32 to f64
    %244 = arith.extsi %242 : i32 to i64
    %245 = llvm.getelementptr %228[%244] : (!llvm.ptr, i64) -> !llvm.ptr, f64
    llvm.store %243, %245 : f64, !llvm.ptr
    %246 = arith.constant 2 : i32
    %247 = arith.extsi %246 : i32 to i64
    llvm.store %247, %67 : i64, !llvm.ptr
    cf.br ^bb36
    ^bb36:
    %248 = llvm.load %67 : !llvm.ptr -> i64
    %249 = arith.cmpi sle, %248, %arg0 : i64
    cf.cond_br %249, ^bb37, ^bb38
    ^bb37:
      %251 = llvm.load %67 : !llvm.ptr -> i64
      %252 = llvm.getelementptr %0[%251] : (!llvm.ptr, i64) -> !llvm.ptr, f64
      %250 = llvm.load %252 : !llvm.ptr -> f64
      %254 = llvm.load %67 : !llvm.ptr -> i64
      %255 = arith.muli %254, %arg0 : i64
      %256 = arith.constant 0 : i32
      %258 = arith.extsi %256 : i32 to i64
      %257 = arith.addi %255, %258 : i64
      %259 = llvm.getelementptr %42[%257] : (!llvm.ptr, i64) -> !llvm.ptr, f64
      %253 = llvm.load %259 : !llvm.ptr -> f64
      %260 = arith.subf %250, %253 : f64
      %262 = llvm.load %67 : !llvm.ptr -> i64
      %263 = llvm.getelementptr %0[%262] : (!llvm.ptr, i64) -> !llvm.ptr, f64
      %261 = llvm.load %263 : !llvm.ptr -> f64
      %264 = llvm.mlir.constant(1 : i64) : i64
      %265 = llvm.alloca %264 x f64 : (i64) -> !llvm.ptr
      llvm.store %261, %265 : f64, !llvm.ptr
      %266 = arith.constant 1 : i32
      %267 = arith.extsi %266 : i32 to i64
      %268 = llvm.mlir.constant(1 : i64) : i64
      %269 = llvm.alloca %268 x i64 : (i64) -> !llvm.ptr
      llvm.store %267, %269 : i64, !llvm.ptr
      cf.br ^bb39
      ^bb39:
      %270 = llvm.load %269 : !llvm.ptr -> i64
      %271 = llvm.load %67 : !llvm.ptr -> i64
      %272 = arith.cmpi slt, %270, %271 : i64
      cf.cond_br %272, ^bb40, ^bb41
      ^bb40:
        %273 = llvm.load %265 : !llvm.ptr -> f64
        %275 = llvm.load %67 : !llvm.ptr -> i64
        %276 = arith.muli %275, %arg0 : i64
        %277 = llvm.load %269 : !llvm.ptr -> i64
        %278 = arith.addi %276, %277 : i64
        %279 = llvm.getelementptr %42[%278] : (!llvm.ptr, i64) -> !llvm.ptr, f64
        %274 = llvm.load %279 : !llvm.ptr -> f64
        %281 = llvm.load %67 : !llvm.ptr -> i64
        %282 = llvm.load %269 : !llvm.ptr -> i64
        %283 = arith.subi %281, %282 : i64
        %284 = llvm.getelementptr %228[%283] : (!llvm.ptr, i64) -> !llvm.ptr, f64
        %280 = llvm.load %284 : !llvm.ptr -> f64
        %285 = arith.mulf %274, %280 : f64
        %286 = arith.addf %273, %285 : f64
        llvm.store %286, %265 : f64, !llvm.ptr
        %287 = llvm.load %269 : !llvm.ptr -> i64
        %288 = arith.constant 1 : i32
        %290 = arith.extsi %288 : i32 to i64
        %289 = arith.addi %287, %290 : i64
        llvm.store %289, %269 : i64, !llvm.ptr
        cf.br ^bb39
      ^bb41:
      %291 = llvm.load %265 : !llvm.ptr -> f64
      %292 = arith.divf %291, %260 : f64
      %293 = llvm.load %67 : !llvm.ptr -> i64
      %294 = llvm.getelementptr %228[%293] : (!llvm.ptr, i64) -> !llvm.ptr, f64
      llvm.store %292, %294 : f64, !llvm.ptr
      %295 = llvm.load %67 : !llvm.ptr -> i64
      %296 = arith.constant 1 : i32
      %298 = arith.extsi %296 : i32 to i64
      %297 = arith.addi %295, %298 : i64
      llvm.store %297, %67 : i64, !llvm.ptr
      cf.br ^bb36
    ^bb38:
    %299 = arith.constant 0.0 : f32
    %300 = arith.extf %299 : f32 to f64
    %301 = llvm.mlir.constant(1 : i64) : i64
    %302 = llvm.alloca %301 x f64 : (i64) -> !llvm.ptr
    llvm.store %300, %302 : f64, !llvm.ptr
    %303 = arith.constant 0 : i32
    %304 = arith.extsi %303 : i32 to i64
    %305 = llvm.mlir.constant(1 : i64) : i64
    %306 = llvm.alloca %305 x i64 : (i64) -> !llvm.ptr
    llvm.store %304, %306 : i64, !llvm.ptr
    cf.br ^bb42
    ^bb42:
    %307 = llvm.load %306 : !llvm.ptr -> i64
    %308 = arith.cmpi slt, %307, %arg0 : i64
    cf.cond_br %308, ^bb43, ^bb44
    ^bb43:
      %309 = llvm.load %302 : !llvm.ptr -> f64
      %311 = arith.muli %arg0, %arg0 : i64
      %312 = llvm.load %306 : !llvm.ptr -> i64
      %313 = arith.addi %311, %312 : i64
      %314 = llvm.getelementptr %42[%313] : (!llvm.ptr, i64) -> !llvm.ptr, f64
      %310 = llvm.load %314 : !llvm.ptr -> f64
      %316 = llvm.getelementptr %0[%arg0] : (!llvm.ptr, i64) -> !llvm.ptr, f64
      %315 = llvm.load %316 : !llvm.ptr -> f64
      %317 = arith.divf %310, %315 : f64
      %319 = llvm.load %306 : !llvm.ptr -> i64
      %320 = arith.subi %arg0, %319 : i64
      %321 = llvm.getelementptr %228[%320] : (!llvm.ptr, i64) -> !llvm.ptr, f64
      %318 = llvm.load %321 : !llvm.ptr -> f64
      %322 = arith.mulf %317, %318 : f64
      %323 = arith.addf %309, %322 : f64
      llvm.store %323, %302 : f64, !llvm.ptr
      %324 = llvm.load %306 : !llvm.ptr -> i64
      %325 = arith.constant 1 : i32
      %327 = arith.extsi %325 : i32 to i64
      %326 = arith.addi %324, %327 : i64
      llvm.store %326, %306 : i64, !llvm.ptr
      cf.br ^bb42
    ^bb44:
    func.call @free(%228) : (!llvm.ptr) -> ()
    func.call @free(%42) : (!llvm.ptr) -> ()
    func.call @free(%0) : (!llvm.ptr) -> ()
    %331 = llvm.load %302 : !llvm.ptr -> f64
    func.return %331 : f64
  }
  func.func @main() -> i32 {
    %333 = arith.constant 52 : i32
    %334 = arith.extsi %333 : i32 to i64
    %332 = func.call @expected_shuffles(%334) : (i64) -> f64
    %335 = arith.constant 100000000.0 : f32
    %337 = arith.extf %335 : f32 to f64
    %336 = arith.mulf %332, %337 : f64
    %338 = func.call @floor(%336) : (f64) -> f64
    %339 = arith.fptosi %338 : f64 to i64
    %340 = llvm.mlir.constant(1 : i64) : i64
    %341 = llvm.alloca %340 x i64 : (i64) -> !llvm.ptr
    llvm.store %339, %341 : i64, !llvm.ptr
    %342 = llvm.load %341 : !llvm.ptr -> i64
    %343 = arith.sitofp %342 : i64 to f64
    %344 = arith.subf %336, %343 : f64
    %345 = arith.constant 0.5 : f32
    %347 = arith.extf %345 : f32 to f64
    %346 = arith.cmpf oge, %344, %347 : f64
    cf.cond_br %346, ^bb45, ^bb46
    ^bb45:
      %348 = llvm.load %341 : !llvm.ptr -> i64
      %349 = arith.constant 1 : i32
      %351 = arith.extsi %349 : i32 to i64
      %350 = arith.addi %348, %351 : i64
      llvm.store %350, %341 : i64, !llvm.ptr
      cf.br ^bb47
    ^bb46:
      cf.br ^bb47
    ^bb47:
    %352 = llvm.load %341 : !llvm.ptr -> i64
    %353 = arith.constant 100000000 : i32
    %355 = arith.extsi %353 : i32 to i64
    %354 = arith.divsi %352, %355 : i64
    %356 = llvm.load %341 : !llvm.ptr -> i64
    %357 = arith.constant 100000000 : i32
    %359 = arith.extsi %357 : i32 to i64
    %358 = arith.remsi %356, %359 : i64
    %360 = llvm.mlir.addressof @str_0 : !llvm.ptr
    %361 = llvm.call @printf(%360, %354, %358) vararg(!llvm.func<i32 (ptr, ...)>) : (!llvm.ptr, i64, i64) -> i32
    %362 = arith.constant 0 : i32
    func.return %362 : i32
  }
}