1 #include "symmetry.h"
2
3 #include "printer.h"
4 #include "log.h"
5 #include <iostream>
6
7 #include <map>
8 using namespace std;
9
10 class Trie
11 {
12 class TrieNode
13 {
14 typedef map<int,class TrieNode> Map;
15 Map m;
16 int value;//used for storing index in vector of permutations
17 public:
TrieNode()18 TrieNode():
19 value(-1)
20 {
21
22 }
TrieNode(IntegerVector const & v,int i,int value_)23 TrieNode(IntegerVector const &v, int i, int value_)
24 {
25 if(i<v.size())
26 m[v[i]]=TrieNode(v,i+1,value_);
27 else
28 value=value_;
29 }
stabilizerSize(IntegerVector const & v,int i) const30 int stabilizerSize(IntegerVector const &v, int i)const
31 {
32 int ret=0;
33 if(i==v.size())return 1;
34 for(Map::const_iterator j=m.begin();j!=m.end();j++)
35 {
36 if(v[i]==v[j->first])
37 ret+=j->second.stabilizerSize(v,i+1);
38 }
39 return ret;
40 }
search(IntegerVector const & v,IntegerVector & building,IntegerVector & tempPerm,IntegerVector & ret,IntegerVector & optimal,int i,bool & isImproving,int * value_=0) const41 void search(IntegerVector const &v, IntegerVector &building, IntegerVector &tempPerm, IntegerVector &ret, IntegerVector &optimal, int i, bool &isImproving, int *value_=0)const
42 {
43 if(i==v.size()){ret=tempPerm;optimal=building;isImproving=false;if(value_)*value_=value;return;}
44 if(isImproving)
45 building[i]=-0x7fffffff;
46 else
47 building[i]=optimal[i];
48 for(Map::const_iterator j=m.begin();j!=m.end();j++)
49 if(v[j->first]>building[i])
50 {
51 isImproving=true;
52 building[i]=v[j->first];
53 }
54 for(Map::const_iterator j=m.begin();j!=m.end();j++)
55 if(v[j->first]==building[i])
56 {
57 tempPerm[i]=j->first;
58 j->second.search(v,building,tempPerm,ret,optimal,i+1,isImproving,value_);
59 }
60 }
searchStabalizer(IntegerVector const & v,IntegerVector & building,IntegerVector & tempPerm,IntegerVector & ret,IntegerVector & optimal,int i,bool & isImproving,IntegerVector const & toBeFixed) const61 void searchStabalizer(IntegerVector const &v, IntegerVector &building, IntegerVector &tempPerm, IntegerVector &ret, IntegerVector &optimal, int i, bool &isImproving, IntegerVector const &toBeFixed)const
62 {
63 if(i==v.size())
64 if(!(SymmetryGroup::compose(tempPerm,v)<optimal))
65 {
66 ret=tempPerm;
67 optimal=SymmetryGroup::compose(tempPerm,v);
68 return;
69 }
70 for(Map::const_iterator j=m.begin();j!=m.end();j++)
71 if(toBeFixed[i]==toBeFixed[j->first])
72 {
73 tempPerm[i]=j->first;
74 j->second.searchStabalizer(v,building,tempPerm,ret,optimal,i+1,isImproving,toBeFixed);
75 }
76 }
77 /* this code contains mistakes void searchStabalizer(IntegerVector const &v, IntegerVector &building, IntegerVector &tempPerm, IntegerVector &ret, IntegerVector &optimal, int i, bool &isImproving, IntegerVector const &toBeFixed)const
78 {
79 if(i==v.size()){ret=tempPerm;optimal=building;isImproving=false;debug<<"DEEP";return;}
80 if(isImproving)
81 building[i]=-0x7fffffff;
82 else
83 building[i]=optimal[i];
84 for(Map::const_iterator j=m.begin();j!=m.end();j++)
85 if(toBeFixed[i]==toBeFixed[j->first])
86 if(v[j->first]>building[i])
87 {
88 isImproving=true;
89 building[i]=v[j->first];
90 }
91 for(Map::const_iterator j=m.begin();j!=m.end();j++)
92 if(toBeFixed[i]==toBeFixed[j->first])
93 if(v[j->first]==building[i])
94 {
95 debug.printInteger(i);debug<<":";
96 debug.printInteger(j->first);debug<<" ";
97 tempPerm[i]=j->first;
98 j->second.searchStabalizer(v,building,tempPerm,ret,optimal,i+1,isImproving,toBeFixed);
99 }
100 }*/
101 // void doubleSearch();
insert(IntegerVector const & v,int i,int value_)102 void insert(IntegerVector const &v, int i, int value_)
103 {
104 if(i==v.size()){value=value_;return;}
105 if(m.count(v[i]))
106 m[v[i]].insert(v,i+1,value_);
107 else
108 m[v[i]]= TrieNode(v,i+1,value_);
109 }
print(int i,int n) const110 void print(int i, int n)const
111 {
112 if(i==n){debug<<"Value:"<<value<<"\n";return;}
113 for(Map::const_iterator j=m.begin();j!=m.end();j++)
114 {
115 {for(int j=0;j<2*i;j++)debug<<" ";}
116 debug.printInteger(j->first);
117 debug<<"\n";
118 j->second.print(i+1,n);
119 }
120 }
size(int i,int n) const121 int size(int i,int n)const
122 {
123 if(i==n)return 1;
124 int ret=0;
125 for(Map::const_iterator j=m.begin();j!=m.end();j++)
126 ret+=j->second.size(i+1,n);
127 return ret;
128 }
129 };
130 public:
131 TrieNode theTree;
132 int n;
Trie(int n_)133 Trie(int n_):
134 n(n_),
135 theTree(SymmetryGroup::identity(n_),0,0)
136 {
137 }
size() const138 int size()const
139 {
140 return theTree.size(0,n);
141 }
insert(IntegerVector const & v,int value)142 void insert(IntegerVector const &v, int value)
143 {
144 theTree.insert(v,0,value);
145 // debug<<v;
146 // theTree.print(0,v.size());
147
148 // debug<<"---------------------------------------------\n";
149 }
150 /**
151 * returns the sigma from the set with sigma(v) maximal in the lexicographic ordering.
152 */
search(IntegerVector const & v,int * value=0)153 IntegerVector search(IntegerVector const &v, int *value=0)
154 {
155 IntegerVector tempPerm(v.size());
156 IntegerVector ret(v.size());
157 IntegerVector building(v.size());
158 IntegerVector optimal=v;//the identity is always in the trie
159 bool isImproving=true;
160 theTree.search(v,building,tempPerm,ret,optimal,0,isImproving,value);
161 return ret;
162 }
searchStabalizer(IntegerVector const & v,IntegerVector const & toBeFixed)163 IntegerVector searchStabalizer(IntegerVector const &v, IntegerVector const &toBeFixed)
164 {
165 IntegerVector tempPerm=SymmetryGroup::identity(v.size());
166 IntegerVector ret(v.size());
167 IntegerVector building(v.size());
168 IntegerVector optimal=v;//the identity is always in the trie
169 bool isImproving=true;
170 theTree.searchStabalizer(v,building,tempPerm,ret,optimal,0,isImproving,toBeFixed);
171 return ret;
172 }
stabilizerSize(IntegerVector const & v) const173 int stabilizerSize(IntegerVector const &v)const
174 {
175 return theTree.stabilizerSize(v,0);
176 }
177 };
178
179
180
181
182
183
184
identity(int n)185 IntegerVector SymmetryGroup::identity(int n)
186 {
187 IntegerVector v(n);
188 for(int i=0;i<n;i++)v[i]=i;
189
190 return v;
191 }
192
193
inverse(IntegerVector const & a)194 IntegerVector SymmetryGroup::inverse(IntegerVector const &a)
195 {
196 return composeInverse(a,identity(a.size()));
197 }
198
199
SymmetryGroup(int n)200 SymmetryGroup::SymmetryGroup(int n):
201 byteTable(0),
202 trie(0)
203 {
204 elements.push_back(identity(n));
205 }
206
207
sizeOfBaseSet() const208 int SymmetryGroup::sizeOfBaseSet()const
209 {
210 assert(!elements.empty());
211 return elements.begin()->size();
212 }
213 /*
214 void SymmetryGroup::computeClosure(IntegerVector const &v) //does this work??
215 {
216 ElementContainer newOnes;
217
218 newOnes.insert(v);
219
220 while(!newOnes.empty())
221 {
222 static int i;
223 i++;
224 if((i&127)==0)fprintf(Stderr,"%i\n",i);
225
226
227 IntegerVector v=*newOnes.begin();
228 for(ElementContainer::const_iterator i=elements.begin();i!=elements.end();i++)
229 {
230 {
231 IntegerVector n(compose(*i,v));
232 if(0==elements.count(n))
233 newOnes.insert(n);
234 }
235 {
236 IntegerVector n(compose(v,*i));
237 if(0==elements.count(n))
238 newOnes.insert(n);
239 }
240 }
241 newOnes.erase(v);
242 elements.insert(v);
243 }
244 }
245 */
246
computeClosure(IntegerVectorList const & l)247 void SymmetryGroup::computeClosure(IntegerVectorList const &l)
248 {
249 // for(IntegerVectorList::const_iterator i=l.begin();i!=l.end();i++)
250 // computeClosure(*i);
251
252 ElementContainer2 elements2;
253 for(ElementContainer::const_iterator i=elements.begin();i!=elements.end();i++)elements2.insert(*i);
254
255 bool growing=true;
256 while(growing)
257 {
258 growing=false;
259 for(ElementContainer2::const_iterator i=elements2.begin();i!=elements2.end();i++)
260 {
261 for(IntegerVectorList::const_iterator j=l.begin();j!=l.end();j++)
262 {
263 {
264 IntegerVector n(compose(*i,*j));
265 growing|=(0==elements2.count(n));
266 elements2.insert(n);
267 }
268 {
269 IntegerVector n(compose(*i,*j));
270 growing|=(0==elements2.count(n));
271 elements2.insert(n);
272 }
273 }
274 }
275 }
276 elements=ElementContainer();
277 for(ElementContainer2::const_iterator i=elements2.begin();i!=elements2.end();i++)elements.push_back(*i);
278 }
279
getUniqueGenerators() const280 IntegerVectorList SymmetryGroup::getUniqueGenerators()const
281 {
282 int n=sizeOfBaseSet();
283 IntegerVectorList ret;
284
285 restart:
286 SymmetryGroup temp(n);
287 temp.computeClosure(ret);
288 ElementContainer::const_iterator j=temp.elements.begin();
289 for(ElementContainer::const_iterator i=elements.begin();i!=elements.end();i++,j++)
290 {
291 if(j==temp.elements.end()||*j!=*i)
292 {
293 ret.push_back(*i);
294 goto restart;
295 }
296 }
297 return ret;
298 }
299
print(FILE * f)300 void SymmetryGroup::print(FILE *f)
301 {
302 AsciiPrinter P(f);
303 P.printString("Printing SymmetryGroup\n");
304 IntegerVectorList l;
305 for(ElementContainer::const_iterator i=elements.begin();i!=elements.end();i++)
306 {
307 // P.printVector(*i);
308 // P.printNewLine();
309 l.push_back(*i);
310 }
311 P.printVectorList(l);
312 fprintf(f,"Group order=%i\n",(int)elements.size());
313 P.printString("Done printing SymmetryGroup.\n");
314 }
315
316
compose(IntegerVector const & perm,IntegerVector const & b)317 IntegerVector SymmetryGroup::compose(IntegerVector const &perm, IntegerVector const &b)
318 {
319 IntegerVector v(perm);
320 assert(perm.size()==b.size());
321 for(int i=0;i<perm.size();i++)v[i]=b[perm[i]];
322 return v;
323 }
324
composeAssign(IntegerVector const & perm,IntegerVector const & b,IntegerVector & dest)325 void SymmetryGroup::composeAssign(IntegerVector const &perm, IntegerVector const &b, IntegerVector &dest)
326 {
327 if(dest.size()!=perm.size())dest=IntegerVector(perm.size());
328 assert(perm.size()==b.size());
329 for(int i=0;i<perm.size();i++)dest[i]=b[perm[i]];
330 }
331
composeInverse(IntegerVector const & perm,IntegerVector const & b)332 IntegerVector SymmetryGroup::composeInverse(IntegerVector const &perm, IntegerVector const &b)
333 {
334 IntegerVector v(perm);
335 assert(perm.size()==b.size());
336 for(int i=0;i<perm.size();i++)v[perm[i]]=b[i];
337 return v;
338 }
339
340
permuteInverseIntegerVectorList(IntegerVector const & perm,IntegerVectorList const & l)341 IntegerVectorList SymmetryGroup::permuteInverseIntegerVectorList(IntegerVector const &perm, IntegerVectorList const &l)
342 {
343 IntegerVectorList ret;
344 for(IntegerVectorList::const_iterator i=l.begin();i!=l.end();i++)
345 ret.push_back(composeInverse(perm,*i));
346
347 return ret;
348 }
349
350
permuteIntegerVectorList(IntegerVectorList const & l,IntegerVector const & v)351 IntegerVectorList SymmetryGroup::permuteIntegerVectorList(IntegerVectorList const &l, IntegerVector const &v)
352 {
353 IntegerVectorList ret;
354 for(IntegerVectorList::const_iterator i=l.begin();i!=l.end();i++)
355 ret.push_back(compose(v,*i));
356
357 return ret;
358 }
359
360
appendPermutedIntegerVectorList(IntegerVectorList const & l,IntegerVector const & perm,IntegerVectorList & dest)361 void SymmetryGroup::appendPermutedIntegerVectorList(IntegerVectorList const &l, IntegerVector const &perm, IntegerVectorList &dest)
362 {
363 int n=perm.size();
364 for(IntegerVectorList::const_iterator i=l.begin();i!=l.end();i++)
365 {
366 dest.push_back(IntegerVector(n));
367 IntegerVector & v=dest.back();
368 for(int j=0;j<n;j++)v[j]=i->UNCHECKEDACCESS(perm.UNCHECKEDACCESS(j));
369 }
370 }
371
permutePolynomial(Polynomial const & p,IntegerVector const & v)372 Polynomial SymmetryGroup::permutePolynomial(Polynomial const &p, IntegerVector const &v)
373 {
374 Polynomial q(p.getRing());
375
376 for(TermMap::const_iterator i=p.terms.begin();i!=p.terms.end();i++)
377 {
378 q+=Term(i->second,Monomial(p.getRing(),compose(v,i->first.exponent)));
379 }
380
381 q.mark(Monomial(p.getRing(),compose(v,p.getMarked().m.exponent)));
382
383 return q;
384 }
385
386
permutePolynomialSet(PolynomialSet const & s,IntegerVector const & v)387 PolynomialSet SymmetryGroup::permutePolynomialSet(PolynomialSet const &s, IntegerVector const &v)
388 {
389 PolynomialRing theRing=s.getRing();
390 PolynomialSet ret(theRing);
391 for(PolynomialSet::const_iterator i=s.begin();i!=s.end();i++)
392 {
393 ret.push_back(permutePolynomial(*i,v));
394 }
395
396 return ret;
397 }
398
399
computeUniqueRepresentative(Polynomial p)400 Polynomial SymmetryGroup::computeUniqueRepresentative(Polynomial p)
401 {
402 Polynomial best=p;
403
404 for(ElementContainer::const_iterator i=elements.begin();i!=elements.end();i++)
405 {
406 Polynomial q=permutePolynomial(p,*i);
407 if(PolynomialCompare()(best,q))best=q;
408 }
409 return best;
410 }
411
412
orbitRepresentative(IntegerVector const & v,IntegerVector * usedPermutation) const413 IntegerVector SymmetryGroup::orbitRepresentative(IntegerVector const &v, IntegerVector *usedPermutation)const
414 {
415 if(trie){
416 if(usedPermutation)
417 {
418 *usedPermutation=trie->search(v);
419 return compose(*usedPermutation,v);
420 }
421 return compose(trie->search(v),v);
422 }
423 IntegerVector ret=v;
424 ElementContainer::const_iterator usedPerm;
425 for(ElementContainer::const_iterator i=elements.begin();i!=elements.end();i++)
426 {
427 IntegerVector q=compose(*i,v);
428 if(! (q<ret))//negation to make sure that usedPerm is set
429 {
430 usedPerm=i;
431 ret=q;
432 }
433 }
434
435 if(usedPermutation)*usedPermutation=*usedPerm;
436
437 if(trie)
438 {
439 // debug<<"Input"<<v<<"\n";
440 // debug<<"Bruteforce"<<ret<<"\n";
441 IntegerVector triePerm=trie->search(v);
442 // debug<<"Trie"<<compose(triePerm,v)<<"\n";
443 assert((compose(triePerm,v)-ret).isZero());
444 }
445
446 return ret;
447 }
448
orbitRepresentative(IntegerVector const & v,int & usedPermutationIndex) const449 IntegerVector SymmetryGroup::orbitRepresentative(IntegerVector const &v, int &usedPermutationIndex)const
450 {
451 if(trie){
452 // return compose(trie->search(v,&usedPermutationIndex),v);
453 IntegerVector temp=compose(trie->search(v,&usedPermutationIndex),v);
454 assert((temp-compose(elements[usedPermutationIndex],v)).isZero());
455 return temp;
456 }
457 IntegerVector ret=v;
458 ElementContainer::const_iterator usedPerm;
459 for(ElementContainer::const_iterator i=elements.begin();i!=elements.end();i++)
460 {
461 IntegerVector q=compose(*i,v);
462 if(! (q<ret))//negation to make sure that usedPerm is set
463 {
464 usedPerm=i;
465 ret=q;
466 }
467 }
468
469 usedPermutationIndex=usedPerm-elements.begin();
470
471 return ret;
472 }
473
474
referenceToIthVector(int index) const475 IntegerVector const &SymmetryGroup::referenceToIthVector(int index)const
476 {
477 return elements[index];
478 }
479
480
orbitRepresentativeFixing(IntegerVector const & v,IntegerVector const & fixed) const481 IntegerVector SymmetryGroup::orbitRepresentativeFixing(IntegerVector const &v, IntegerVector const &fixed)const
482 {
483 if(trie){
484 return compose(trie->searchStabalizer(v,fixed),v);
485 }
486 IntegerVector ret=v;
487
488 for(ElementContainer::const_iterator i=elements.begin();i!=elements.end();i++)
489 if(compose(*i,fixed)==fixed)
490 {
491 IntegerVector q=compose(*i,v);
492 if(ret<q)ret=q;
493 }
494 if(trie){
495 IntegerVector temp=compose(trie->searchStabalizer(v,fixed),v);
496 // debug<<"Input"<<v;
497 // debug<<"Brute"<<ret;
498 // debug<<"Quick"<<temp;
499 assert((temp-ret).isZero());
500 // return compose(trie->searchStabalizer(v,fixed),v);
501 }
502 return ret;
503 }
504
isPermutation(IntegerVector const & a)505 bool SymmetryGroup::isPermutation(IntegerVector const &a)
506 {
507 int n=a.size();
508 IntegerVector temp(n);
509 for(int i=0;i<n;i++)temp[i]=-1;
510 for(int i=0;i<n;i++)
511 {
512 if(a[i]<0 || a[i]>=n)return false;
513 temp[i]=i;
514 }
515 for(int i=0;i<n;i++)if(temp[i]<0)return false;
516 return true;
517 }
518
519
combinePermutationAndSignChanges(IntegerVector const & permutation,IntegerVector const & signChanges)520 IntegerVector SymmetryGroup::combinePermutationAndSignChanges(IntegerVector const &permutation, IntegerVector const &signChanges)
521 {
522 assert(isPermutation(permutation));
523 int n=permutation.size();
524 assert(n==signChanges.size());
525 IntegerVector ret(2*n);
526 for(int i=0;i<n;i++)
527 if(signChanges[i]==1)
528 {
529 ret[i]=permutation[i];
530 ret[i+n]=n+permutation[i];
531 }
532 else
533 {
534 ret[i]=n+permutation[i];
535 ret[i+n]=permutation[i];
536 }
537 return ret;
538 }
539
extractPermuationAndSignChanges(IntegerVector const & v,IntegerVector & permutation,IntegerVector & signChanges)540 void SymmetryGroup::extractPermuationAndSignChanges(IntegerVector const &v, IntegerVector &permutation, IntegerVector &signChanges)
541 {
542 int n=v.size()/2;
543 permutation=IntegerVector(n);
544 signChanges=IntegerVector(n);
545
546 for(int i=0;i<n;i++)
547 {
548 permutation[i]=v[i]%n;
549 if(v[i]<n)
550 signChanges[i]=1;
551 else
552 signChanges[i]=-1;
553 }
554 }
555
556
orbitSize(IntegerVector const & stable) const557 int SymmetryGroup::orbitSize(IntegerVector const &stable)const
558 {
559 int groupSize=elements.size();
560
561 int n=stable.size();
562 int numFixed=0;
563
564 if(trie)
565 {
566 numFixed=trie->stabilizerSize(stable);
567 }
568 else
569 {
570 for(SymmetryGroup::ElementContainer::const_iterator j=elements.begin();j!=elements.end();j++)
571 {
572 bool doesFix=true;
573
574 for(int i=0;i<n;i++)
575 if(stable[i]!=stable[(*j)[i]])
576 {
577 doesFix=false;
578 break;
579 }
580 if(doesFix)numFixed++;
581 }
582 }
583 return groupSize/numFixed;
584 }
585
586
fundamentalDomainInequality(IntegerVector const & perm,bool alternative)587 IntegerVector SymmetryGroup::fundamentalDomainInequality(IntegerVector const &perm, bool alternative)
588 {
589 if(alternative)return identity(perm.size())-perm;
590 for(int i=0;i<perm.size();i++)
591 if(perm[i]!=i)
592 return IntegerVector::standardVector(perm.size(),i)-IntegerVector::standardVector(perm.size(),perm[i]);
593 // return -IntegerVector::standardVector(perm.size(),i)-IntegerVector::standardVector(perm.size(),perm[i]);//USE this for 4x4 of 5x5
594 return IntegerVector(perm.size());
595 }
596
597
fundamentalDomainInequalities(bool alternative) const598 IntegerVectorList SymmetryGroup::fundamentalDomainInequalities(bool alternative)const
599 {
600 set<IntegerVector> ret2;
601 for(ElementContainer::const_iterator i=elements.begin();i!=elements.end();i++)
602 ret2.insert(fundamentalDomainInequality(*i,alternative));
603
604 IntegerVectorList ret;
605 for(set<IntegerVector>::const_iterator i=ret2.begin();i!=ret2.end();i++)
606 if(!i->isZero())ret.push_back(*i);
607
608 return ret;
609 }
610
611
createByteTable()612 void SymmetryGroup::createByteTable()
613 {
614 assert(!byteTable);
615 int n=sizeOfBaseSet();
616 byteTableHeight=elements.size();
617 byteTable=(unsigned char*)malloc(n*byteTableHeight*sizeof(unsigned char));
618 assert(byteTable);
619 int j=0;
620 for(ElementContainer::const_iterator i=elements.begin();i!=elements.end();i++,j++)
621 {
622 for(int k=0;k<n;k++)
623 byteTable[j*n+k]=(*i)[k];
624 }
625 }
626
createTrie()627 void SymmetryGroup::createTrie()
628 {
629 log1 debug<<"Creating symmetry trie.\n";
630 trie=new Trie(sizeOfBaseSet());
631 int I=0;
632 for(ElementContainer::const_iterator i=elements.begin();i!=elements.end();i++,I++)
633 trie->insert(*i,I);
634 log2 debug<<"Number of elements";log2 debug.printInteger(trie->size());log2 debug<<"\n";
635 log1 debug<<"Done creating symmetry trie.\n";
636
637 if(0)
638 {
639 trie->theTree.print(0,elements[0].size());
640 I=0;
641 for(ElementContainer::const_iterator i=elements.begin();i!=elements.end();i++,I++)
642 {
643 debug<<I<<*i<<"\n";
644 }
645 }
646 }
647
648
getByteTable() const649 unsigned char * SymmetryGroup::getByteTable()const
650 {
651 return byteTable;
652 }
653
654
getByteTableHeight() const655 int SymmetryGroup::getByteTableHeight()const
656 {
657 return byteTableHeight;
658 }
659
660
isTrivial() const661 bool SymmetryGroup::isTrivial()const
662 {
663 ElementContainer::const_iterator i=elements.begin();
664 assert(i!=elements.end());
665 i++;
666 return i==elements.end();
667 }
668
stabilizer(IntegerVector const & v) const669 IntegerVectorList SymmetryGroup::stabilizer(IntegerVector const &v)const
670 {
671 IntegerVectorList ret;
672 for(ElementContainer::const_iterator i=elements.begin();i!=elements.end();i++)
673 if((compose(*i,v)-v).isZero())ret.push_back(*i);
674 return ret;
675 }
676
677
mergeSortRek(IntegerVector & v,int begin,int end,IntegerVector & temp)678 static int mergeSortRek(IntegerVector &v, int begin, int end, IntegerVector &temp)
679 {
680 if(end-begin<2)return 0;
681 int med=(begin+end)>>1;
682 int nswaps=mergeSortRek(v,begin,med,temp);
683 nswaps+=mergeSortRek(v,med,end,temp);
684
685 {
686 int Astart=begin;
687 int Alength=med-begin;
688 int Bstart=med;
689 int Blength=end-med;
690 int nextFree=begin;
691 while(nextFree!=end)
692 {
693 // debug<<"Astart:"<<Astart<<"Alength:"<<Alength<<"Bstart:"<<Bstart<<"Blength:"<<Blength<<"nextFree:"<<nextFree<<"\n";
694 if(Blength==0 || (Alength!=0 && v[Astart]<v[Bstart]))
695 {
696 temp[nextFree++]=v[Astart++];
697 Alength--;
698 }
699 else
700 {
701 temp[nextFree++]=v[Bstart++];
702 nswaps+=Alength;
703 Blength--;
704 }
705 }
706 for(int i=begin;i!=end;i++)v[i]=temp[i];
707 }
708 //debug<<"return\n";
709 return nswaps;
710 }
711
mergeSort(IntegerVector & v)712 int mergeSort(IntegerVector &v)
713 {
714 IntegerVector temp(v.size());
715 return mergeSortRek(v,0,v.size(),temp);
716 }
717
718