001 /** 002 * CliffordBitSet.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 PARTICif(blade > spaceMask) 022 throw ULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 023 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 024 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 025 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 026 * DEALINGS IN THE SOFTWARE. 027 */ 028 029 package jclifford; 030 031 import java.util.Iterator; 032 import java.util.Map; 033 import java.util.TreeMap; 034 035 /** 036 * <p>This class represents a BitSet - value map implementation of the Clifford element and all the operation in an arbitrary dimension space.</p> 037 * @version <p>0.9</p> 038 * @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> 039 * @see Clifford 040 * @see CliffordTreeSet 041 */ 042 public class CliffordBitSet{ 043 044 /** 045 * Precision. 046 */ 047 private static double eps = 1e-12; 048 049 /** 050 * Blade-value mappings of the element. 051 */ 052 private TreeMap map; 053 054 /** 055 * Creates and returns an element with no blade-value mappings. 056 */ 057 public CliffordBitSet() 058 { 059 map = new TreeMap(); 060 } 061 062 /** 063 * Gets the value of a blade. 064 * @param blade the blade whose value is to be retrieved. 065 * @return the value of the specified blade, 0.0 if blade is not present. 066 */ 067 public final double get(BladeBitSet blade) 068 { 069 Value val = (Value) map.get(blade); 070 return (val != null) ? val.value : 0.0; 071 } 072 073 /** 074 * Gets the value of a blade. 075 * @param blade the binary mask representing the specified blade (format is "i, j, ...", where i, j are versor indexes) whose value is to be retrieved. 076 * @return the value of the specified blade, 0.0 if blade is not present. 077 */ 078 public final double get(String blade) 079 { 080 return get(new BladeBitSet(blade)); 081 } 082 083 /** 084 * Puts a new blade-value mapping or updates existing. 085 * @param blade the specified blade that is to be put. 086 * @param value the corresponding value of the specified blade. 087 */ 088 public final void put(BladeBitSet blade, double value) 089 { 090 map.put(blade.clone(), new Value(value)); 091 } 092 093 /** 094 * Puts a new blade-value mapping or updates existing. 095 * @param blade the binary mask representing the specified blade (format is "i, j, ...", where i, j are versor indexes) that is to be put. 096 * @param value the corresponding value of the specified blade. 097 */ 098 public final void put(String blade, double value) 099 { 100 map.put(new BladeBitSet(blade), new Value(value)); 101 } 102 103 /** 104 * Removes blade-value mapping if existing. 105 * @param blade the specified blade that is to be removed. 106 */ 107 public final void remove(BladeBitSet blade) 108 { 109 map.remove(blade); 110 } 111 112 /** 113 * Removes blade-value mapping if existing. 114 * @param blade the binary mask representing the specified blade (format is "i, j, ...", where i, j are versor indexes) that is to be removed. 115 */ 116 public final void remove(String blade) 117 { 118 map.remove(new BladeBitSet(blade)); 119 } 120 121 /** 122 * Returns a string representation of this element. 123 * @return the string representation of this element. 124 */ 125 public String toString() 126 { 127 //String representation of the element 128 String str = new String(); 129 //Temporary reference variables 130 Map.Entry entry; 131 BladeBitSet bld; 132 Value val; 133 //For all blade-value mappings 134 Iterator it = map.entrySet().iterator(); 135 while(it.hasNext()) { 136 //Getting blade and value 137 entry = (Map.Entry) it.next(); 138 bld = (BladeBitSet) entry.getKey(); 139 val = (Value) entry.getValue(); 140 //Printing blade-value mapping 141 str += bld.toString() + "\t\t==>\t\t" + val.toString() + "\n"; 142 } 143 str += "----------------\n"; 144 //Returning the string 145 return str; 146 } 147 148 /** 149 * Creates and returns an element deeply cloning this element. 150 */ 151 public Object clone() 152 { 153 //Creating a new empty element 154 CliffordBitSet newcl = new CliffordBitSet(); 155 //Temporary reference variables 156 Map.Entry entry; 157 BladeBitSet bld; 158 Value val; 159 //For all blade-value mappings 160 Iterator it = map.entrySet().iterator(); 161 while(it.hasNext()) { 162 //Getting blade and value 163 entry = (Map.Entry) it.next(); 164 bld = (BladeBitSet) entry.getKey(); 165 val = (Value) entry.getValue(); 166 //Adding a copy of blade-value mapping to newcl 167 newcl.map.put(bld.clone(), val.clone()); 168 } 169 return newcl; 170 } 171 172 /** 173 * Removes blades with values lower than eps. 174 */ 175 public final void noZero() 176 { 177 //Temporary reference variables 178 Map.Entry entry; 179 Value val; 180 //For all blade-value mappings 181 Iterator it = map.entrySet().iterator(); 182 while(it.hasNext()) { 183 entry = (Map.Entry) it.next(); 184 val = (Value) entry.getValue(); 185 //Tresholding 186 if(java.lang.Math.abs(val.value) < eps) 187 //Removing blade-value mappings 188 it.remove(); 189 } 190 } 191 192 /** 193 * Computes the quad module of an element discarding signature. 194 * @return the quad module of the specified element discarding signature. 195 */ 196 public final double uQuadMod() 197 { 198 //Temporary unsigned quad module 199 double uqm = 0.0; 200 //Temporary reference variables 201 Map.Entry entry; 202 Value val; 203 //For all blade-value mappings 204 Iterator it = map.entrySet().iterator(); 205 while(it.hasNext()) { 206 //Getting value 207 entry = (Map.Entry) it.next(); 208 val = (Value) entry.getValue(); 209 //Uptdating temporary module 210 uqm += val.value * val.value; 211 } 212 return uqm; 213 } 214 215 /** 216 * Normalizes this element respect the unsigned module. 217 */ 218 public final void normalize() 219 { 220 //Unsigned module 221 double um = Math.sqrt(uQuadMod()); 222 //Checking for null module 223 if(um == 0.0) 224 return; 225 //Temporary reference variables 226 Map.Entry entry; 227 BladeBitSet bld; 228 Value val; 229 //For all blade-value mappings 230 Iterator it = map.entrySet().iterator(); 231 while(it.hasNext()) { 232 entry = (Map.Entry) it.next(); 233 bld = (BladeBitSet) entry.getKey(); 234 val = (Value) entry.getValue(); 235 //Updating value 236 val.value /= um; 237 //Tresholding 238 if(java.lang.Math.abs(val.value) < eps) 239 //Removing blade-value mappings 240 it.remove(); 241 } 242 } 243 244 /** 245 * Gets highest grade of this element. 246 * @return highest grade of this element. 247 */ 248 public final int getMaxGrade()//Not using entrySet().iterator 249 { 250 //Temporary grade 251 int maxgrade = 0, bldgrade; 252 //Temporary reference variable 253 BladeBitSet bld; 254 //Defining an array of blades 255 Object[] arrbld = map.keySet().toArray(); 256 //For all cl blades 257 for(int x = 0; x < arrbld.length; x ++){ 258 //Getting blade 259 bld = (BladeBitSet) arrbld[x]; 260 //Comparing blade grade with temporary grade 261 bldgrade = bld.getGrade(); 262 if(bldgrade > maxgrade) 263 maxgrade = bldgrade; 264 } 265 return maxgrade; 266 } 267 268 /** 269 * Verifies if this element is a scalar. 270 * @return true if this element is a scalar, false otherwise. 271 */ 272 public final boolean isScalar() 273 { 274 return (getMaxGrade() == 0) ? true : false; 275 } 276 277 /** 278 * Verifies if this element is a scalar. 279 * @return true if this element is a scalar, false otherwise. 280 */ 281 public final boolean isZero() 282 { 283 return ((get(new BladeBitSet()) == 0.0) && (getMaxGrade() == 0)) ? true : false; 284 } 285 286 /** 287 * Verifies if this element is a vector. 288 * @return true if this element is a vector, false otherwise. 289 */ 290 public final boolean isVector() 291 { 292 return ((get(new BladeBitSet()) == 0.0) && (getMaxGrade() == 1)) ? true : false; 293 } 294 295 /** 296 * Gets highest dimension present in this element. 297 * @return highest present in this element. 298 */ 299 public final int getMaxDimension()//Not using entrySet().iterator 300 { 301 //Temporary grade 302 int maxdim = 0, bldmaxdim; 303 //Temporary reference variable 304 BladeBitSet bld; 305 //Defining an array of blades 306 Object[] arrbld = map.keySet().toArray(); 307 //For all cl blades 308 for(int x = 0; x < arrbld.length; x ++){ 309 //Getting blade 310 bld = (BladeBitSet) arrbld[x]; 311 //Comparing blade grade with temporary grade 312 bldmaxdim = bld.getMaxDimension(); 313 if(bldmaxdim > maxdim) 314 maxdim = bldmaxdim; 315 } 316 return maxdim; 317 } 318 319 /** 320 * Compares this element with the specified element for equality. 321 * Two elements are considered equals if they have same blades and corresponding values differing less than tollerance. 322 * @param obj the second element that is to be compared. 323 * @return true if this Element and the specified element are equals, false otherwise. 324 */ 325 public boolean equals(Object obj) 326 { 327 //Casting to Clifford object 328 CliffordBitSet cl = (CliffordBitSet) obj; 329 //Verifyng if elements have the same size (number of blade-value mappings) 330 if(map.size() != cl.map.size()) 331 return false; 332 //Tollerance 333 double tol = 2 * eps; 334 //Temporary reference variables 335 Map.Entry entry1, entry2; 336 BladeBitSet bld1, bld2; 337 Value val1, val2; 338 //For all blade-value mappings 339 Iterator it1 = map.entrySet().iterator(); 340 Iterator it2 = cl.map.entrySet().iterator(); 341 while(it1.hasNext()) { 342 entry1 = (Map.Entry) it1.next(); 343 entry2 = (Map.Entry) it2.next(); 344 //Getting blades 345 bld1 = (BladeBitSet) entry1.getKey(); 346 bld2 = (BladeBitSet) entry2.getKey(); 347 //Comparing blades 348 if(!bld1.equals(bld2)) 349 return false; 350 //Getting values 351 val1 = (Value) entry1.getValue(); 352 val2 = (Value) entry2.getValue(); 353 //Comparing values 354 if(java.lang.Math.abs(val1.value - val2.value) > tol) 355 return false; 356 } 357 //Elements are equals 358 return true; 359 } 360 361 /** 362 * Computes the sum with the specified element. 363 * @param cl the second element of the sum. 364 * @return a new element from the sum with the specified element. 365 */ 366 public final CliffordBitSet add(final CliffordBitSet cl) 367 { 368 //Creating a new empty element 369 CliffordBitSet newcl = (CliffordBitSet) clone(); 370 //Temporary reference variables 371 Map.Entry entry2; 372 BladeBitSet bld2; 373 Value val2, newval; 374 //For all cl blade-value mappings 375 Iterator it2 = cl.map.entrySet().iterator(); 376 while(it2.hasNext()) { 377 //Getting blade and value 378 entry2 = (Map.Entry) it2.next(); 379 bld2 = (BladeBitSet) entry2.getKey(); 380 val2 = (Value) entry2.getValue(); 381 //Searching bld2 in newcl 382 newval = (Value) newcl.map.get(bld2); 383 //If newcl already contains bld2 384 if(newval != null) 385 //Updating corresponding value 386 newval.value += val2.value; 387 else 388 //Adding new blade-value mappings to newcl 389 newcl.map.put(bld2.clone(),new Value(val2.value)); 390 } 391 //Returning tresholded element 392 return newcl; 393 } 394 395 /** 396 * Computes the difference with the specified element. 397 * @param cl the second element of the difference. 398 * @return a new element subtracting the second specified element from this. 399 */ 400 public final CliffordBitSet sub(final CliffordBitSet cl) 401 { 402 //Creating a new empty element 403 CliffordBitSet newcl = (CliffordBitSet) clone(); 404 //Temporary reference variables 405 Map.Entry entry2; 406 BladeBitSet bld2; 407 Value val2, newval; 408 //For all cl blade-value mappings 409 Iterator it2 = cl.map.entrySet().iterator(); 410 while(it2.hasNext()) { 411 //Getting blade and value 412 entry2 = (Map.Entry) it2.next(); 413 bld2 = (BladeBitSet) entry2.getKey(); 414 val2 = (Value) entry2.getValue(); 415 //Searching bld2 in newcl 416 newval = (Value) newcl.map.get(bld2); 417 //If newcl already contains bld2 418 if(newval != null) 419 //Updating corresponding value 420 newval.value -= val2.value; 421 else 422 //Adding new blade-value mappings to newcl 423 newcl.map.put(bld2.clone(),new Value(-val2.value)); 424 } 425 //Returning tresholded element 426 return newcl; 427 } 428 429 /** 430 * Computes the grade involution of this element. 431 * @return a new element from the grade involution of the specified element. 432 */ 433 public final CliffordBitSet gradeInv() 434 { 435 //Creating a new empty element 436 CliffordBitSet newcl = new CliffordBitSet(); 437 //Resulting value 438 double result; 439 //Temporary reference variables 440 Map.Entry entry; 441 BladeBitSet bld; 442 Value val; 443 //For all blade-value mappings 444 Iterator it = map.entrySet().iterator(); 445 while(it.hasNext()) { 446 //Getting blade and value 447 entry = (Map.Entry) it.next(); 448 bld = (BladeBitSet) entry.getKey(); 449 val = (Value) entry.getValue(); 450 //Computing resulting value regarding parity of the grade (number of inversions) 451 result = ((bld.getGrade() & 1) != 0) ? -val.value : val.value; 452 //Adding new blade-value mapping to newcl 453 newcl.map.put(bld.clone(), new Value(result)); 454 } 455 return newcl; 456 } 457 458 /** 459 * Computes the reverse of this element. 460 * @return a new element from the reversion of this element. 461 */ 462 public final CliffordBitSet rev() 463 { 464 //Creating a new empty element 465 CliffordBitSet newcl = new CliffordBitSet(); 466 //Resulting value 467 double result; 468 //Temporary reference variables 469 Map.Entry entry; 470 BladeBitSet bld; 471 Value val; 472 //For all blade-value mappings 473 Iterator it = map.entrySet().iterator(); 474 while(it.hasNext()) { 475 //Getting blade and value 476 entry = (Map.Entry) it.next(); 477 bld = (BladeBitSet) entry.getKey(); 478 val = (Value) entry.getValue(); 479 /* 480 Computing resulting value regarding the sign: (-1)^((r(r-1))/2) 481 Sign only depends upon the odd-ness or even-ness of the number of transpositions 482 required to get things back in order. This obeys a simple recurrance relationship. 483 Let T(n) be the number of transpositions required to revert an n-form. 484 Then, T(n+1) = T(n) + n - 1 because it will require T(n) transpositions to reorder 485 the first n subscripts and n-1 transpositions to get the n+1-th subscript from one 486 end of the list to the other. 487 So odd-ness or even-ness of T(n+4) is the same as that of T(n), because: 488 T(n+4) = T(n+3) + n + 2 = T(n+2) + 2n + 3 = T(n+1) + 3n + 3 = T(n) + 4n + 2 489 And, because T(0) and T(1) are even while T(2) and T(3) are odd an n-form requires: 490 an odd number of transpositions to revert if n = 2 or n = 3 modulo 4. 491 In code, this translates to whether the second bit of the grade is set. 492 */ 493 result = ((bld.getGrade() & 2) != 0) ? -val.value : val.value; 494 //Adding new blade-value mapping to newcl 495 newcl.map.put(bld.clone(), new Value(result)); 496 } 497 return newcl; 498 } 499 500 /** 501 * Computes the inverse of this element. 502 * @return a new element from the inversion of this element. 503 */ 504 public final CliffordBitSet inv() 505 { 506 //Creating a new empty element 507 CliffordBitSet newcl = new CliffordBitSet(); 508 //Temporary sign 509 boolean sign; 510 //Resulting value 511 double result; 512 //Temporary module 513 double module = 0.0; 514 //Temporary reference variables 515 Map.Entry entry; 516 BladeBitSet bld; 517 Value val; 518 //For all blade-value mappings 519 Iterator it = map.entrySet().iterator(); 520 while(it.hasNext()) { 521 //Getting blade and value 522 entry = (Map.Entry) it.next(); 523 bld = (BladeBitSet) entry.getKey(); 524 val = (Value) entry.getValue(); 525 //Computing resulting sign 526 sign = ((bld.getGrade() & 2) != 0) ? true : false; 527 //Computing resulting value 528 result = sign ? -val.value : val.value; 529 //Adding new blade-value mapping to newcl 530 newcl.map.put(bld.clone(), new Value(result)); 531 //Updating temporary module 532 module += val.value * ((bld.getSign(bld) ^ sign) ? -val.value : val.value); 533 } 534 return newcl.gP(1/module); 535 } 536 537 /** 538 * Computes the conjugation of this element. 539 * The conjugation of an element is a grade involution and a reversion. 540 * @return a new element from the conjugation of the specified element. 541 */ 542 public final CliffordBitSet conj() 543 { 544 //Creating a new empty element 545 CliffordBitSet newcl = new CliffordBitSet(); 546 //Resulting value 547 double result = 0.0; 548 //Temporary reference variables 549 Map.Entry entry; 550 BladeBitSet bld; 551 Value val; 552 //For all blade-value mappings 553 Iterator it = map.entrySet().iterator(); 554 while(it.hasNext()) { 555 //Getting blade and value 556 entry = (Map.Entry) it.next(); 557 bld = (BladeBitSet) entry.getKey(); 558 val = (Value) entry.getValue(); 559 //Computing resulting value: it is a grade involution and a reversion. 560 switch(bld.getGrade() & 3){ 561 case 0: 562 case 3: 563 result = val.value; 564 break; 565 case 1: 566 case 2: 567 result = -val.value; 568 break; 569 } 570 //Adding new blade-value mapping to newcl 571 newcl.map.put(bld.clone(), new Value(result)); 572 } 573 return newcl; 574 } 575 576 /** 577 * Computes the geometric product with the specified scalar. 578 * @param scalar the scalar of the geometric product. 579 * @return a new element from the geometric product with the specified scalar. 580 */ 581 public final CliffordBitSet gP(double scalar) 582 { 583 //Creating a new empty element 584 CliffordBitSet newcl = new CliffordBitSet(); 585 double newvalue; 586 //Temporary reference variables 587 Map.Entry entry; 588 BladeBitSet bld; 589 Value val; 590 //For all blade-value mappings 591 Iterator it = map.entrySet().iterator(); 592 while(it.hasNext()) { 593 //Getting blade and value 594 entry = (Map.Entry) it.next(); 595 bld = (BladeBitSet) entry.getKey(); 596 val = (Value) entry.getValue(); 597 //Resulting value for newcl bld 598 newvalue = val.value * scalar; 599 //Tresholding 600 if(java.lang.Math.abs(newvalue) > eps) 601 //Adding new blade-value mapping to newcl blades map 602 newcl.map.put(bld.clone(), new Value(newvalue)); 603 } 604 return newcl; 605 } 606 607 608 /** 609 * Computes the geometric product with the specified element. 610 * @param cl the second element of the geometric product. 611 * @return a new element from the geometric product with the specified element. 612 */ 613 public final CliffordBitSet gP(final CliffordBitSet cl) 614 { 615 //Creating a new empty element 616 CliffordBitSet newcl = new CliffordBitSet(); 617 //Temporary reference variables 618 Map.Entry entry1, entry2; 619 BladeBitSet bld1, bld2, newbld; 620 Value val1, val2, newval; 621 double result; 622 //For all blade-value mappings 623 Iterator it1 = map.entrySet().iterator(), it2; 624 while(it1.hasNext()) { 625 //Getting blade and value 626 entry1 = (Map.Entry) it1.next(); 627 bld1 = (BladeBitSet) entry1.getKey(); 628 val1 = (Value) entry1.getValue(); 629 //For all cl blade-value mappings 630 it2 = cl.map.entrySet().iterator(); 631 while(it2.hasNext()) { 632 //Getting blade and value 633 entry2 = (Map.Entry) it2.next(); 634 bld2 = (BladeBitSet) entry2.getKey(); 635 val2 = (Value) entry2.getValue(); 636 //Computing resulting blade 637 newbld = bld1.geometricProduct(bld2); 638 //Computing resulting value (regarding the sign) 639 result = val1.value * (bld1.getSign(bld2) ? -val2.value : val2.value); 640 //Searching newbld in newcl 641 newval = (Value) newcl.map.get(newbld); 642 //Updating newval by adding result 643 if(newval != null) 644 newval.value += result; 645 //Adding new blade-value mapping to newcl 646 else 647 newcl.map.put(newbld, new Value(result)); 648 } 649 } 650 //Returning tresholded element 651 newcl.noZero(); 652 return newcl; 653 } 654 655 /** 656 * Computes the wedge product with the specified element. 657 * @param cl the second element of the wedge product. 658 * @return a new element from the wedge product with the specified element. 659 */ 660 public final CliffordBitSet wP(final CliffordBitSet cl) 661 { 662 //Creating a new empty element 663 CliffordBitSet newcl = new CliffordBitSet(); 664 //Temporary reference variables 665 Map.Entry entry1, entry2; 666 BladeBitSet bld1, bld2, newbld; 667 Value val1, val2, newval; 668 double result; 669 //For all blade-value mappings 670 Iterator it1 = map.entrySet().iterator(), it2; 671 while(it1.hasNext()) { 672 //Getting blade and value 673 entry1 = (Map.Entry) it1.next(); 674 bld1 = (BladeBitSet) entry1.getKey(); 675 val1 = (Value) entry1.getValue(); 676 //For all cl blade-value mappings 677 it2 = cl.map.entrySet().iterator(); 678 while(it2.hasNext()) { 679 //Getting blade and value 680 entry2 = (Map.Entry) it2.next(); 681 bld2 = (BladeBitSet) entry2.getKey(); 682 val2 = (Value) entry2.getValue(); 683 //Computing resulting blade 684 newbld = bld1.wedgeProduct(bld2); 685 //If bld1 and bld2 have common versor wedge product is null 686 if(newbld == null) continue; 687 //Computing resulting value (regarding the sign) 688 result = val1.value * (bld1.getSign(bld2) ? -val2.value : val2.value); 689 //Searching newbld in newcl 690 newval = (Value) newcl.map.get(newbld); 691 //Updating newval by adding result 692 if(newval != null) 693 newval.value += result; 694 //Adding new blade-value mapping to newcl 695 else 696 newcl.map.put(newbld, new Value(result)); 697 } 698 } 699 //Returning tresholded element 700 newcl.noZero(); 701 return newcl; 702 } 703 704 /** 705 * Computes the left contraction with the specified element. 706 * @param cl the second element of the left contraction. 707 * @return a new element from the left contraction with the specified element. 708 */ 709 public final CliffordBitSet lC(final CliffordBitSet cl) 710 { 711 //Creating a new empty element 712 CliffordBitSet newcl = new CliffordBitSet(); 713 //Temporary reference variables 714 Map.Entry entry1, entry2; 715 BladeBitSet bld1, bld2, newbld; 716 Value val1, val2, newval; 717 double result; 718 //For all blade-value mappings 719 Iterator it1 = map.entrySet().iterator(), it2; 720 while(it1.hasNext()) { 721 //Getting blade and value 722 entry1 = (Map.Entry) it1.next(); 723 bld1 = (BladeBitSet) entry1.getKey(); 724 val1 = (Value) entry1.getValue(); 725 //For all cl blade-value mappings 726 it2 = cl.map.entrySet().iterator(); 727 while(it2.hasNext()) { 728 //Getting blade and value 729 entry2 = (Map.Entry) it2.next(); 730 bld2 = (BladeBitSet) entry2.getKey(); 731 val2 = (Value) entry2.getValue(); 732 //Computing resulting blade 733 newbld = bld1.leftContraction(bld2); 734 //If bld1 versors are not a subset of bld2 versors left contraction is null 735 if(newbld == null) continue; 736 //Computing resulting value (regarding the sign) 737 result = val1.value * (bld1.getSign(bld2) ? -val2.value : val2.value); 738 //Searching newbld in newcl 739 newval = (Value) newcl.map.get(newbld); 740 //Updating newval by adding result 741 if(newval != null) 742 newval.value += result; 743 //Adding new blade-value mapping to newcl 744 else 745 newcl.map.put(newbld, new Value(result)); 746 } 747 } 748 //Returning tresholded element 749 newcl.noZero(); 750 return newcl; 751 } 752 753 /** 754 * Computes the right contraction with the specified element. 755 * @param cl the second element of the right contraction. 756 * @return a new element from the right contraction with the specified element. 757 */ 758 public final CliffordBitSet rC(final CliffordBitSet cl) 759 { 760 //Creating a new empty element 761 CliffordBitSet newcl = new CliffordBitSet(); 762 //Temporary reference variables 763 Map.Entry entry1, entry2; 764 BladeBitSet bld1, bld2, newbld; 765 Value val1, val2, newval; 766 double result; 767 //For all blade-value mappings 768 Iterator it1 = map.entrySet().iterator(), it2; 769 while(it1.hasNext()) { 770 //Getting blade and value 771 entry1 = (Map.Entry) it1.next(); 772 bld1 = (BladeBitSet) entry1.getKey(); 773 val1 = (Value) entry1.getValue(); 774 //Defining an iterator on cl2 blade-value mappings 775 it2 = cl.map.entrySet().iterator(); 776 //For all cl blade-value mappings 777 while(it2.hasNext()) { 778 //Getting blade and value 779 entry2 = (Map.Entry) it2.next(); 780 bld2 = (BladeBitSet) entry2.getKey(); 781 val2 = (Value) entry2.getValue(); 782 //Computing resulting blade 783 newbld = bld1.rightContraction(bld2); 784 //If bld2 versors are not a subset of bld1 versors right contraction is null 785 if(newbld == null) continue; 786 //Computing resulting value (regarding the sign) 787 result = val1.value * (bld1.getSign(bld2) ? -val2.value : val2.value); 788 //Searching newbld in newcl 789 newval = (Value) newcl.map.get(newbld); 790 //Updating newval by adding result 791 if(newval != null) 792 newval.value += result; 793 //Adding new blade-value mapping to newcl 794 else 795 newcl.map.put(newbld, new Value(result)); 796 } 797 } 798 //Returning tresholded element 799 newcl.noZero(); 800 return newcl; 801 } 802 803 /** 804 * Computes the meet with the specified element in a common subspace. 805 * @param cl the second element of the meet. 806 * @param i the element representing a common subspace. 807 * @return a new element from the meet with the specified element. 808 */ 809 public final CliffordBitSet meet(final CliffordBitSet cl, final CliffordBitSet i){ 810 return (gP(i)).lC(cl); 811 } 812 813 }