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 }