001    /**
002     * CliffordTreeSet.java
003     *
004     * This file is part of jclifford package and it's distributed under the terms of the MIT license.
005     *
006     * The MIT License :
007     * -----------------
008     * Copyright (c) 2002, 2003, 2004, 2005 Giorgio Vassallo, Pietro Brignola
009     *
010     * Permission is hereby granted, free of charge, to any person obtaining a
011     * copy of this software and associated documentation files (the "Software"),
012     * to deal in the Software without restriction, including without limitation
013     * the rights to use, copy, modify, merge, publish, distribute, sublicense,
014     * and/or sell copies of the Software, and to permit persons to whom the
015     * Software is furnished to do so, subject to the following conditions:
016     * The above copyright notice and this permission notice shall be included in
017     * all copies or substantial portions of the Software.
018     *
019     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
020     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
021     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
022     * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
023     * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
024     * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
025     * DEALINGS IN THE SOFTWARE.
026     */
027    
028    package jclifford;
029    
030    import java.util.Iterator;
031    import java.util.Map;
032    import java.util.TreeMap;
033    
034    /**
035     * <p>This class represents a TreeSet - value map implementation of the Clifford element and all the operation in an arbitrary dimension space.</p>
036     * @version <p>0.9</p>
037     * @author <p>Realized by <a href="mailto:vassallo@csai.unipa.it">Giorgio Vassallo</a>, <a href="mailto:pietro.brignola@libero.it">Pietro Brignola</a>, November 2002.</p>
038     * @see Clifford
039     * @see CliffordBitSet
040     */
041    public class CliffordTreeSet{
042    
043            /**
044             * Blade-value mappings of the element.
045             */
046            private TreeMap map;
047    
048            /**
049             * Creates and returns an element with no blade-value mappings.
050             */
051            public CliffordTreeSet()
052            {
053                    map = new TreeMap();
054            }
055    
056            /**
057             * Gets the value of a blade.
058             * @param blade the blade whose value is to be retrieved.
059             * @return the value of the specified blade, 0.0 if blade is not present in this element.
060             */
061            public final double get(BladeTreeSet blade)
062            {
063                    Value val = (Value) map.get(blade);
064                    return (val != null) ? val.value : 0.0;
065            }
066    
067            /**
068             * Puts a new blade-value mapping or updates existing.
069             * @param blade the specified blade that is to be put.
070             * @param value the corresponding value of the specified blade.
071             */
072            public final void put(BladeTreeSet blade, double value)
073            {
074                    map.put(blade.clone(), new Value(value));
075            }
076    
077            /**
078             * Removes blade-value mapping if existing.
079             * @param blade the int representing the specified blade that is to be removed.
080             */
081            public final void remove(BladeTreeSet blade)
082            {
083                    map.remove(blade);
084            }
085    
086            /**
087             * Computes the sum with the specified element.
088             * @param cl the second element of the sum.
089             * @return a new element from the sum with the specified element.
090             */
091            public CliffordTreeSet add(final CliffordTreeSet cl)
092            {
093                    //Creating a new empty element
094                    CliffordTreeSet newcl = (CliffordTreeSet) this.clone();
095                    //Temporary reference variables
096                    Map.Entry entry;
097                    BladeTreeSet bld2;
098                    Value val2, newval;
099                    //For all cl blade-value mappings
100                    Iterator it2 = cl.map.entrySet().iterator();
101                    while(it2.hasNext()) {
102                            //Getting blade and value
103                            entry = (Map.Entry) it2.next();
104                            bld2 = (BladeTreeSet) entry.getKey();
105                            val2 = (Value) entry.getValue();
106                            //Searching bld2 in newcl
107                            newval = (Value) newcl.map.get(bld2);
108                            //If newcl already contains bld2
109                            if(newval != null)
110                                    //Updating corresponding value
111                                    newval.value += val2.value;
112                            else
113                                    //Adding new blade-value mappings to newcl
114                                    newcl.map.put(bld2.clone(),val2.clone());
115                    }
116                    //Returning tresholded element
117                    return newcl;
118            }
119    
120            /**
121             * Computes the difference with the specified element.
122             * @param cl the second element of the difference.
123             * @return a new element subtracting the second specified element from this.
124             */
125            public CliffordTreeSet sub(final CliffordTreeSet cl)
126            {
127                    //Creating a new empty element
128                    CliffordTreeSet newcl = (CliffordTreeSet) this.clone();
129                    //Temporary reference variables
130                    Map.Entry entry;
131                    BladeTreeSet bld2;
132                    Value val2, newval;
133                    //For all cl blade-value mappings
134                    Iterator it2 = cl.map.entrySet().iterator();
135                    while(it2.hasNext()) {
136                            //Getting blade and value
137                            entry = (Map.Entry) it2.next();
138                            bld2 = (BladeTreeSet) entry.getKey();
139                            val2 = (Value) entry.getValue();
140                            //Searching bld2 in newcl
141                            newval = (Value) newcl.map.get(bld2);
142                            //If newcl already contains bld2
143                            if(newval != null)
144                                    //Updating corresponding value
145                                    newval.value -= val2.value;
146                            else
147                                    //Adding new blade-value mappings to newcl
148                                    newcl.map.put(bld2.clone(),new Value(-val2.value));
149                    }
150                    //Returning tresholded element
151                    return newcl;
152            }
153            
154            /**
155             * Computes the geometric product with the specified scalar.
156             * @param scalar the scalar of the geometric product.
157             * @return a new element from the geometric product with the specified scalar.
158             */
159            public CliffordTreeSet gP(double scalar)
160            {
161                    //Creating a new empty element
162                    CliffordTreeSet newcl = new CliffordTreeSet();
163                    double newvalue;
164                    //Temporary reference variables
165                    Map.Entry entry;
166                    BladeTreeSet bld;
167                    Value val;
168                    //For all blade-value mappings
169                    Iterator it = map.entrySet().iterator();
170                    while(it.hasNext()) {
171                            //Getting blade and value
172                            entry = (Map.Entry) it.next();
173                            bld = (BladeTreeSet) entry.getKey();
174                            val = (Value) entry.getValue();
175                            //Resulting value for newcl bld
176                            newvalue = val.value * scalar;
177                            //Tresholding
178                            if(java.lang.Math.abs(newvalue) > 1e-13)
179                                    //Adding new blade-value mapping to newcl blades map
180                                    newcl.map.put(bld.clone(), new Value(newvalue));
181                    }
182                    return newcl;
183            }
184    
185            /**
186             * Computes the geometric product with the specified element.
187             * @param cl the second element of the geometric product.
188             * @return a new element from the geometric product with the specified element.
189             */
190            public CliffordTreeSet gP(final CliffordTreeSet cl)
191            {
192                    //Creating a new empty element
193                    CliffordTreeSet newcl = new CliffordTreeSet();
194                    //Temporary reference variables
195                    Map.Entry entry1, entry2;
196                    BladeTreeSet bld1, bld2, newbld;
197                    Value val1, val2, newval;
198                    double result;
199                    //For all blade-value mappings
200                    Iterator it1 = map.entrySet().iterator(), it2;
201                    while(it1.hasNext()) {
202                            //Getting blade and value
203                            entry1 = (Map.Entry) it1.next();
204                            bld1 = (BladeTreeSet) entry1.getKey();
205                            val1 = (Value) entry1.getValue();
206                            //For all cl blade-value mappings
207                            it2 = cl.map.entrySet().iterator();
208                            while(it2.hasNext()) {
209                                    //Getting blade and value
210                                    entry2 = (Map.Entry) it2.next();
211                                    bld2 = (BladeTreeSet) entry2.getKey();
212                                    val2 = (Value) entry2.getValue();
213                                    //Computing resulting blade
214                                    newbld = bld1.geometricProduct(bld2);
215                                    //Computing resulting value (regarding the sign)
216                                    result = val1.value * (bld1.getSign(bld2) ? -val2.value : val2.value);
217                                    //Searching newbld in newcl
218                                    newval = (Value) newcl.map.get(newbld);
219                                    //Updating newval by adding result
220                                    if(newval != null)
221                                            newval.value += result;
222                                    //Adding new blade-value mapping to newcl
223                                    else
224                                            newcl.map.put(newbld, new Value(result));
225                            }
226                    }
227                    //Returning tresholded element
228                    return newcl;
229            }
230    
231            /**
232             * Computes the wedge product with the specified element.
233             * @param cl the second element of the wedge product.
234             * @return a new element from the wedge product with the specified element.
235             */
236            public CliffordTreeSet wP(final CliffordTreeSet cl)
237            {
238                    //Creating a new empty element
239                    CliffordTreeSet newcl = new CliffordTreeSet();
240                    //Temporary reference variables
241                    Map.Entry entry1, entry2;
242                    BladeTreeSet bld1, bld2, newbld;
243                    Value val1, val2, newval;
244                    double result;
245                    //For all blade-value mappings
246                    Iterator it1 = map.entrySet().iterator(), it2;
247                    while(it1.hasNext()) {
248                            //Getting blade and value
249                            entry1 = (Map.Entry) it1.next();
250                            bld1 = (BladeTreeSet) entry1.getKey();
251                            val1 = (Value) entry1.getValue();
252                            //For all cl blade-value mappings
253                            it2 = cl.map.entrySet().iterator();
254                            while(it2.hasNext()) {
255                                    //Getting blade and value
256                                    entry2 = (Map.Entry) it2.next();
257                                    bld2 = (BladeTreeSet) entry2.getKey();
258                                    val2 = (Value) entry2.getValue();
259                                    //Computing resulting blade
260                                    newbld = bld1.wedgeProduct(bld2);
261                                    //If bld1 and bld2 have common versor wedge product is null
262                                    if(newbld == null) continue;
263                                    //Computing resulting value (regarding the sign)
264                                    result = val1.value * (bld1.getSign(bld2) ? -val2.value : val2.value);
265                                    //Searching newbld in newcl
266                                    newval = (Value) newcl.map.get(newbld);
267                                    //Updating newval by adding result
268                                    if(newval != null)
269                                            newval.value += result;
270                                    //Adding new blade-value mapping to newcl
271                                    else
272                                            newcl.map.put(newbld, new Value(result));
273                            }
274                    }
275                    //Returning tresholded element
276                    return newcl;
277            }
278    
279            /**
280             * Computes the left contraction with the specified element.
281             * @param cl the second element of the left contraction.
282             * @return a new element from the left contraction with the specified element.
283             */
284            public CliffordTreeSet lC(final CliffordTreeSet cl)
285            {
286                    //Creating a new empty element
287                    CliffordTreeSet newcl = new CliffordTreeSet();
288                    //Temporary reference variables
289                    Map.Entry entry1, entry2;
290                    BladeTreeSet bld1, bld2, newbld;
291                    Value val1, val2, newval;
292                    double result;
293                    //For all blade-value mappings
294                    Iterator it1 = map.entrySet().iterator(), it2;
295                    while(it1.hasNext()) {
296                            //Getting blade and value
297                            entry1 = (Map.Entry) it1.next();
298                            bld1 = (BladeTreeSet) entry1.getKey();
299                            val1 = (Value) entry1.getValue();
300                            //For all cl blade-value mappings
301                            it2 = cl.map.entrySet().iterator();
302                            while(it2.hasNext()) {
303                                    //Getting blade and value
304                                    entry2 = (Map.Entry) it2.next();
305                                    bld2 = (BladeTreeSet) entry2.getKey();
306                                    val2 = (Value) entry2.getValue();
307                                    //Computing resulting blade
308                                    newbld = bld1.leftContraction(bld2);
309                                    //If bld1 versors are not a subset of bld2 versors left contraction is null
310                                    if(newbld == null) continue;
311                                    //Computing resulting value (regarding the sign)
312                                    result = val1.value * (bld1.getSign(bld2) ? -val2.value : val2.value);
313                                    //Searching newbld in newcl
314                                    newval = (Value) newcl.map.get(newbld);
315                                    //Updating newval by adding result
316                                    if(newval != null)
317                                            newval.value += result;
318                                    //Adding new blade-value mapping to newcl
319                                    else
320                                            newcl.map.put(newbld, new Value(result));
321                            }
322                    }
323                    //Returning tresholded element
324                    return newcl;
325            }
326    
327            /**
328             * Computes the right contraction with the specified element.
329             * @param cl the second element of the right contraction.
330             * @return a new element from the right contraction with the specified element.
331             */
332            public CliffordTreeSet rC(final CliffordTreeSet cl)
333            {
334                    //Creating a new empty element
335                    CliffordTreeSet newcl = new CliffordTreeSet();
336                    //Temporary reference variables
337                    Map.Entry entry1, entry2;
338                    BladeTreeSet bld1, bld2, newbld;
339                    Value val1, val2, newval;
340                    double result;
341                    //For all blade-value mappings
342                    Iterator it1 = map.entrySet().iterator(), it2;
343                    while(it1.hasNext()) {
344                            //Getting blade and value
345                            entry1 = (Map.Entry) it1.next();
346                            bld1 = (BladeTreeSet) entry1.getKey();
347                            val1 = (Value) entry1.getValue();
348                            //For all cl blade-value mappings
349                            it2 = cl.map.entrySet().iterator();
350                            while(it2.hasNext()) {
351                                    //Getting blade and value
352                                    entry2 = (Map.Entry) it2.next();
353                                    bld2 = (BladeTreeSet) entry2.getKey();
354                                    val2 = (Value) entry2.getValue();
355                                    //Computing resulting blade
356                                    newbld = bld1.rigthContraction(bld2);
357                                    //If bld2 versors are not a subset of bld1 versors right contraction is null
358                                    if(newbld == null) continue;
359                                    //Computing resulting value (regarding the sign)
360                                    result = val1.value * (bld1.getSign(bld2) ? -val2.value : val2.value);
361                                    //Searching newbld in newcl
362                                    newval = (Value) newcl.map.get(newbld);
363                                    //Updating newval by adding result
364                                    if(newval != null)
365                                            newval.value += result;
366                                    //Adding new blade-value mapping to newcl
367                                    else
368                                            newcl.map.put(newbld, new Value(result));
369                            }
370                    }
371                    //Returning tresholded element
372                    return newcl;
373            }
374    
375            /**
376             * Compares this element with the specified element for equality.
377             * Two elements are considered equals if they have same blades and corresponding values differing less than tollerance.
378             * @param cl the second element that is to be compared.
379             * @param tol the tollerance.
380             * @return true if this element and the specified element are equals, false otherwise.
381             */
382            public boolean equals(final CliffordTreeSet cl, double tol)
383            {
384                    //Verifyng if elements have the same size (number of blade-value mappings)
385                    if(map.size() != cl.map.size())
386                            return false;
387                    //Temporary reference variables
388                    Map.Entry entry1, entry2;
389                    BladeTreeSet bld1, bld2;
390                    Value val1, val2;
391                    //For all blade-value mappings
392                    Iterator it1 = map.entrySet().iterator();
393                    Iterator it2 = cl.map.entrySet().iterator();
394                    while(it1.hasNext()) {
395                            entry1 = (Map.Entry) it1.next();
396                            entry2 = (Map.Entry) it2.next();
397                            //Getting blades
398                            bld1 = (BladeTreeSet) entry1.getKey();
399                            bld2 = (BladeTreeSet) entry2.getKey();
400                            //Comparing blades
401                            if(!bld1.equals(bld2))
402                                    return false;
403                            //Getting values
404                            val1 = (Value) entry1.getValue();
405                            val2 = (Value) entry2.getValue();
406                            //Comparing values
407                            if(java.lang.Math.abs(val1.value - val2.value) > tol)
408                                    return false;
409                    }
410                    //Elements are equals
411                    return true;
412            }
413    
414            /**
415             * Creates and returns an element deeply cloning this element.
416             */
417            public Object clone()
418            {
419                    //Creating a new empty element
420                    CliffordTreeSet newcl = new CliffordTreeSet();
421                    //Temporary reference variables
422                    Map.Entry entry;
423                    BladeTreeSet bld;
424                    Value val;
425                    //For all blade-value mappings
426                    Iterator it = map.entrySet().iterator();
427                    while(it.hasNext()) {
428                            //Getting blade and value
429                            entry = (Map.Entry) it.next();
430                            bld = (BladeTreeSet) entry.getKey();
431                            val = (Value) entry.getValue();
432                            //Adding a copy of blade-value mapping to newcl
433                            newcl.map.put(bld.clone(), val.clone());
434                    }
435                    return newcl;
436            }
437    
438            /**
439             * Returns a string representation of this element.
440             * @return the string representation of this element.
441             */
442            public String toString()
443            {
444                    //String representation of the element
445                    String str = new String();
446                    //Temporary reference variables
447                    Map.Entry entry;
448                    BladeTreeSet bld;
449                    Value val;
450                    //For all blade-value mappings
451                    Iterator it = map.entrySet().iterator();
452                    while(it.hasNext()) {
453                            //Getting blade and value
454                            entry = (Map.Entry) it.next();
455                            bld = (BladeTreeSet) entry.getKey();
456                            val = (Value) entry.getValue();
457                            //Printing blade-value mapping
458                            str += bld.toString() + "\t\t==>\t\t" + val.toString() + "\n";
459                    }
460                    str += "----------------\n";
461                    //Returning the string
462                    return str;
463            }
464    
465    }