package meerkat.mixer.network;

/**
 * Generic utilities
 */
public class Util {
    /*
     * Apply a single layer's  switch permutations in place (as implied by {@link PermutationNetwork#setPermutation(int[])})
     * @param values values output by previous layxer
     * @param layer layer to apply (layer is between 1 and numLayers; layer 0 is the input layer)
     * @param <T> type of values.
     */
    public static <T> void applyLayerSwitches(PermutationNetwork net, T[] values, int layer) {
        int numSwitches = net.getNumInputs() >>> 1;
        for (int i = 0; i < numSwitches; ++i) {
            if (net.isCrossed(layer, i)) {
                T tmp = values[i * 2];
                values[i * 2] = values[i * 2 + 1];
                values[i * 2 + 1] = tmp;
            }
        }
    }


    public static <T> void convertOutputPermToInputPerm(PermutationNetwork net, T[] oldValues, T[] newValues, int layer) {
        int numInputs = net.getNumInputs();
        assert(numInputs == oldValues.length);
        assert(numInputs == newValues.length);

        for (int i = 0; i < numInputs; ++i) {
            newValues[i] = oldValues[net.getOutputIdxInPreviousLayer(layer, i)];
        }
    }


    public static <T> void permute(PermutationNetwork net, T[] oldValues, T[] newValues) {
        for (int layer = 0; layer < net.getNumLayers(); ++layer) {
            convertOutputPermToInputPerm(net, oldValues, newValues, layer);
            applyLayerSwitches(net, newValues, layer);
            System.arraycopy(newValues, 0, oldValues, 0, oldValues.length);
        }
    }
}
