package de.gaalop.productComputer; import de.gaalop.productComputer.AlgebraPC; import de.gaalop.productComputer.BladeStr; import de.gaalop.productComputer.BubbleSort; import de.gaalop.tba.Multivector; import java.util.HashMap; import java.util.LinkedList; /** * Computes the product of two blades * @author christian */ public class ProductComputer { private int bitCount; private byte[] squareMask; private HashMap<Integer, SumOfBlades> mapZIToPM; private HashMap<Integer, SumOfBlades> mapPMToZI; private SumOfBlades[] bladeListPM; private HashMap<Blade, Integer> mapBladeToIndex; // ============================ INITIALIZATION ============================ /** * Returns the index of an element in an array * @param element The element to search * @param arr The array to search in * @return The index of the element */ private int getIndex(String element, String[] arr) { for (int i = 0;i<arr.length;i++) if (element.equals(arr[i])) return i; return -1; } /** * Converts a BladeStr instance into an SignedBlade * @param bladeStr The bladeStr instance * @param base The base of the underlying algebra * @return The created SignedBlade */ private SignedBlade bladeStrToSignedBlade(BladeStr bladeStr, String[] base) { SignedBlade sBlade = new SignedBlade(bitCount, bladeStr.getPrefactor()); Integer[] arr = new Integer[bladeStr.getBaseVectors().length]; int i=0; for (String baseVector: bladeStr.getBaseVectors()) { int index = getIndex(baseVector, base); arr[i] = index; sBlade.set(index); i++; } if ((BubbleSort.doBubbleSort(arr) % 2) == 1) sBlade.coefficient *= -1; return sBlade; } /** * Initializes a transformation map * @param base The base of the underlying algebra * @param source The map of the algebra definition * @param dest The destination map */ private void initializeMap(String[] base, String[] base2, HashMap<String, LinkedList<BladeStr>> source, HashMap<Integer, SumOfBlades> dest) { for (String baseElement: source.keySet()) { LinkedList<BladeStr> list = source.get(baseElement); SumOfBlades sumOfBlades = new SumOfBlades(); for (BladeStr element: list) sumOfBlades.add(bladeStrToSignedBlade(element, base)); dest.put(getIndex(baseElement, base2), sumOfBlades); } } /** * Helper function for createBlades. * @param arrTrailing The trailing array to be inserted before each combination * @param startPos The start position in the base array * @param k The number of base elements to be inserted */ private void createBladesHelp(Blade arrTrailing, int startPos, int k, LinkedList<SumOfBlades> bladelist) { if (k == 1) { for (int s=startPos;s<bitCount;++s) { Blade nbase = new Blade(bitCount, arrTrailing); nbase.set(s); SumOfBlades su = new SumOfBlades(); su.add(new SignedBlade(bitCount, nbase)); bladelist.add(su); } } else { for (int s=startPos;s<bitCount-1;++s) { Blade nbase = new Blade(bitCount, arrTrailing); nbase.set(s); createBladesHelp(nbase, s+1, k-1, bladelist); } } } /** * Initializes the ProductComputer using an AlgebraPC instance * @param algebraPC The AlgebraPC instance */ public void initialize(AlgebraPC algebraPC) { bitCount = algebraPC.base.length; //set square mask squareMask = new byte[algebraPC.base2.length]; for (int index = 0;index < algebraPC.base2.length; index++) squareMask[index] = algebraPC.baseSquaresStr.get(algebraPC.base2[index]); //initialise map Zeroinf to Plusminus mapZIToPM = new HashMap<Integer, SumOfBlades>(); initializeMap(algebraPC.base2, algebraPC.base, algebraPC.mapToPlusMinus, mapZIToPM); //initialise map Zeroinf to Plusminus mapPMToZI = new HashMap<Integer, SumOfBlades>(); initializeMap(algebraPC.base, algebraPC.base2, algebraPC.mapToZeroInf, mapPMToZI); //initialize blade list in zero inf base LinkedList<SumOfBlades> bladeListZI = new LinkedList<SumOfBlades>(); SumOfBlades s1 = new SumOfBlades(); s1.add(new SignedBlade(bitCount)); bladeListZI.add(s1); for (int k=1;k<=bitCount;k++) { Blade list1 = new Blade(bitCount); createBladesHelp(list1, 0, k, bladeListZI); } //fill indices map and convert blade list to plus minus base bladeListPM = new SumOfBlades[bladeListZI.size()]; mapBladeToIndex = new HashMap<Blade, Integer>(); int i=0; for (SumOfBlades s: bladeListZI) { SignedBlade sb = s.getFirst(); mapBladeToIndex.put(new Blade(bitCount, sb), new Integer(i)); bladeListPM[i] = BaseTransformation.transform(s, mapZIToPM, bitCount); i++; } } // ============================ COMPUTATION OF PRODUCTS ============================ /** * Merges equal blades to one blade * @param sumOfBlades */ private void group(SumOfBlades sumOfBlades) { HashMap<Blade, Float> map = new HashMap<Blade, Float>(); for (SignedBlade sb: sumOfBlades) { Blade b = new Blade(bitCount, sb); if (map.containsKey(b)) map.put(b, map.get(b)+sb.coefficient); else map.put(b, sb.coefficient); } sumOfBlades.clear(); for (Blade b: map.keySet()) { float prefactor = map.get(b); if (Math.abs(prefactor) > 10E-4) sumOfBlades.add(new SignedBlade(bitCount, b, prefactor)); } } /** * Computes a product of two blades * @param factor1 The index of the first blade * @param factor2 The index of the second blade * @param calculator The calculator to be used * @return The product of the two blades */ public Multivector calcProduct(Integer factor1, Integer factor2, ProductCalculator calculator) { SumOfBlades s1 = bladeListPM[factor1]; SumOfBlades s2 = bladeListPM[factor2]; SumOfBlades product = new SumOfBlades(); for (SignedBlade b1: s1) for (SignedBlade b2: s2) calculator.calcProduct(b1,b2,product,bitCount,squareMask); product = BaseTransformation.transform(product, mapPMToZI, bitCount); group(product); return product.toMultivector(mapBladeToIndex, bitCount); } }