// 
// Decompiled by Procyon v0.6.0
// 

package org.bouncycastle.math.ec;

import java.math.BigInteger;

public class FixedPointUtil
{
    public static final String PRECOMP_NAME = "bc_fixed_point";
    
    public static int getCombSize(final ECCurve ecCurve) {
        final BigInteger order = ecCurve.getOrder();
        return (order == null) ? (ecCurve.getFieldSize() + 1) : order.bitLength();
    }
    
    public static FixedPointPreCompInfo getFixedPointPreCompInfo(final PreCompInfo preCompInfo) {
        return (preCompInfo instanceof FixedPointPreCompInfo) ? ((FixedPointPreCompInfo)preCompInfo) : null;
    }
    
    public static FixedPointPreCompInfo precompute(final ECPoint ecPoint) {
        final ECCurve curve = ecPoint.getCurve();
        return (FixedPointPreCompInfo)curve.precompute(ecPoint, "bc_fixed_point", new PreCompCallback() {
            @Override
            public PreCompInfo precompute(final PreCompInfo preCompInfo) {
                final FixedPointPreCompInfo fixedPointPreCompInfo = (preCompInfo instanceof FixedPointPreCompInfo) ? ((FixedPointPreCompInfo)preCompInfo) : null;
                final int combSize = FixedPointUtil.getCombSize(curve);
                final int width = (combSize > 250) ? 6 : 5;
                final int n = 1 << width;
                if (this.checkExisting(fixedPointPreCompInfo, n)) {
                    return fixedPointPreCompInfo;
                }
                final int n2 = (combSize + width - 1) / width;
                final ECPoint[] array = new ECPoint[width + 1];
                array[0] = ecPoint;
                for (int i = 1; i < width; ++i) {
                    array[i] = array[i - 1].timesPow2(n2);
                }
                array[width] = array[0].subtract(array[1]);
                curve.normalizeAll(array);
                final ECPoint[] array2 = new ECPoint[n];
                array2[0] = array[0];
                for (int j = width - 1; j >= 0; --j) {
                    final ECPoint ecPoint = array[j];
                    int k;
                    for (int n3 = k = 1 << j; k < n; k += n3 << 1) {
                        array2[k] = array2[k - n3].add(ecPoint);
                    }
                }
                curve.normalizeAll(array2);
                final FixedPointPreCompInfo fixedPointPreCompInfo2 = new FixedPointPreCompInfo();
                fixedPointPreCompInfo2.setLookupTable(curve.createCacheSafeLookupTable(array2, 0, array2.length));
                fixedPointPreCompInfo2.setOffset(array[width]);
                fixedPointPreCompInfo2.setWidth(width);
                return fixedPointPreCompInfo2;
            }
            
            private boolean checkExisting(final FixedPointPreCompInfo fixedPointPreCompInfo, final int n) {
                return fixedPointPreCompInfo != null && this.checkTable(fixedPointPreCompInfo.getLookupTable(), n);
            }
            
            private boolean checkTable(final ECLookupTable ecLookupTable, final int n) {
                return ecLookupTable != null && ecLookupTable.getSize() >= n;
            }
        });
    }
}
