package hj.array;

import edu.rice.cs.mint.runtime.*;

public final class SRegionRectangular {
    
    public final int low_I, low_J, low_K, low_L, low_M;
    public final int lg_I, lg_J, lg_K, lg_L, lg_M;
    public final SafeCode<Integer> clow_I, clow_J, clow_K, clow_L, clow_M;
    public final SafeCode<Integer> clg_I, clg_J, clg_K, clg_L, clg_M;
    public final int rank;
    public final int base;
    
    public SRegionRectangular(final int [] r, final int b) {
        rank = (r.length / 2);
        final int llow_I = low_I = (rank >= 1) ? r[0] : 0; // low bound for dim 1
        final int llg_I = lg_I  = (rank >= 1) ? r[1] - r[0] + 1: 0; // high bound for dim 1
        final int llow_J = low_J = (rank >= 2) ? r[2] : 0;
        final int llg_J  = lg_J  = (rank >= 2) ? r[3] - r[2] + 1: 0;
        final int llow_K = low_K = (rank >= 3) ? r[4] : 0;
        final int llg_K  = lg_K  = (rank >= 3) ? r[5] + r[4] + 1: 0;
        final int llow_L = low_L = (rank >= 4) ? r[6] : 0;
        final int llg_L  = lg_L  = (rank >= 4) ? r[7] + r[6] + 1: 0;
        final int llow_M = low_M = (rank >= 5) ? r[8] : 0;
        final int llg_M  = lg_M  = (rank >= 5) ? r[9] + r[8] + 1: 0;
        
        clow_I = <| llow_I |>;
        clow_J = <| llow_J |>;
        clow_K = <| llow_K |>;
        clow_L = <| llow_L |>;
        clow_M = <| llow_M |>;
        
        clg_I = <| llg_I |>;
        clg_J = <| llg_J |>;
        clg_K = <| llg_K |>;
        clg_L = <| llg_L |>;
        clg_M = <| llg_M |>;
        
        if (rank > 5) {
            throw new RuntimeException("current rectangular region implementation is restricted from 1d to 5d ");
        }

        base = b;
    }
    
    
    public final separable SafeCode<Integer> ordinal(final SafeCode<Integer> i) {
        return <| `i-`clow_I |>;
    }
    
    public final separable SafeCode<Integer> ordinal(final SafeCode<Integer> i, final SafeCode<Integer> j) {
        return <| (`j-`(clow_J)) + (`i-`(clow_I)) * `(clg_J) |>;
    }
    
    public final separable SafeCode<Integer> ordinal(final SafeCode<Integer> i, final SafeCode<Integer> j, final SafeCode<Integer> k) {
        return <| (`k-`(clow_K)) + (`j-`(clow_J))*`(clg_K)+ (`i-`(clow_I))*`(clg_K)*`(clg_J) |>;
    }
    
    public final separable SafeCode<Integer> ordinal(final SafeCode<Integer> i, final SafeCode<Integer> j, final SafeCode<Integer> k, final SafeCode<Integer> l) {
        return <| (`l-`(clow_L)) + (`k-`(clow_K))*`(clg_L) + (`j-`(clow_J))*`(clg_L)*`(clg_K)+ (`i-`(clow_I))*`(clg_L)*`(clg_K)*`(clg_J) |>;
    }
    
    public final separable SafeCode<Integer> ordinal(final SafeCode<Integer> i, final SafeCode<Integer> j, final SafeCode<Integer> k, final SafeCode<Integer> l, final SafeCode<Integer> m) {
        return <| (`m-`(clow_M)) + (`l-`(clow_L))*`(clg_M) + (`k-`(clow_K))*`(clg_M)*`(clg_L) +
            (`j-`(clow_J))*`(clg_M)*`(clg_L)*`(clg_K)+ (`i-`(clow_I))*`(clg_M)*`(clg_L)*`(clg_K)*`(clg_J) |>;
    }
    
    
    public final separable SafeCode<Integer> getDimensionSize(int dimension) {
        if (dimension == 1) {
            return clg_I;
        }
        if (dimension == 2) {
            return clg_J;
        }
        if (dimension == 3) {
            return clg_K;
        }
        if (dimension == 4) {
            return clg_L;
        }
        if (dimension == 5) {
            return clg_M;
        }
        
        throw new RuntimeException("current rectangular region implementation is restricted from 1d to 5d ");
        
    }
    
    public separable SafeCode<String> toStringCode() {
        int dimension = 1;
        SafeCode<String> res = <|""|>;
        while (dimension < 6) {
            res = <| `(res) + "[" + `(getDimensionSize(dimension++)) + "]" |>;
        }
        return res;
    }
    
    public String toString() {
        SafeCode<String> sc = toStringCode();
        return sc.run();
    }
}