Salome HOME
Revert "Synchronize adm files"
[modules/kernel.git] / src / SALOMEDSImpl / SALOMEDSImpl_AttributeTableOfReal.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  File   : SALOMEDSImpl_AttributeTableOfReal.cxx
24 //  Author : Michael Ponikarov
25 //  Module : SALOME
26 //
27 #include "SALOMEDSImpl_AttributeTableOfReal.hxx"
28
29 #include <sstream>
30 #include <algorithm>
31
32 #define SEPARATOR '\1'
33 typedef std::map<int, double>::const_iterator MI;
34
35 static std::string getUnit(const std::string& theString)
36 {
37   std::string aString(theString);
38   int aPos = aString.find(SEPARATOR);
39   return aPos < 0 || aPos == aString.size()-1 ? std::string() : aString.substr(aPos+1, aString.size());
40 }
41
42 static std::string getTitle(const std::string& theString)
43 {
44   std::string aString(theString);
45   int aPos = aString.find(SEPARATOR);
46   return aPos < 0 ? aString :aString.substr(0, aPos);
47 }
48
49 const std::string& SALOMEDSImpl_AttributeTableOfReal::GetID() 
50 {
51   static std::string SALOMEDSImpl_AttributeTableOfRealID ("128371A1-8F52-11d6-A8A3-0001021E8C7F");
52   return SALOMEDSImpl_AttributeTableOfRealID;
53 }
54
55 SALOMEDSImpl_AttributeTableOfReal* SALOMEDSImpl_AttributeTableOfReal::Set(const DF_Label& label) 
56 {
57   SALOMEDSImpl_AttributeTableOfReal* A = NULL;
58   if (!(A=(SALOMEDSImpl_AttributeTableOfReal*)label.FindAttribute(SALOMEDSImpl_AttributeTableOfReal::GetID()))) {
59     A = new SALOMEDSImpl_AttributeTableOfReal();
60     label.AddAttribute(A);
61   }
62   return A;
63 }
64
65 SALOMEDSImpl_AttributeTableOfReal::SALOMEDSImpl_AttributeTableOfReal() 
66 :SALOMEDSImpl_GenericAttribute("AttributeTableOfReal")
67 {
68   myNbRows = 0;
69   myNbColumns = 0;
70 }
71
72 void SALOMEDSImpl_AttributeTableOfReal::SetNbColumns(const int theNbColumns)
73 {
74   CheckLocked();  
75   Backup();
76   
77   std::map<int, double> aMap;
78   aMap = myTable;
79   myTable.clear();
80
81   for(MI p = aMap.begin(); p != aMap.end(); p++) {
82     int aRow = (int)(p->first/myNbColumns) + 1;
83     int aCol = (int)(p->first - myNbColumns*(aRow-1));
84     if(aCol == 0) { aCol = myNbColumns; aRow--; }
85     if(aCol > theNbColumns) continue;
86     int aKey = (aRow-1)*theNbColumns+aCol;
87     myTable[aKey] = p->second;
88   }
89
90   myNbColumns = theNbColumns;
91
92   while (myCols.size() < myNbColumns) { // append empty columns titles
93     myCols.push_back(std::string(""));
94   }
95   
96   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
97 }
98
99 void SALOMEDSImpl_AttributeTableOfReal::SetTitle(const std::string& theTitle) 
100 {
101   CheckLocked();  
102   Backup();
103   myTitle = theTitle;
104   
105   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
106 }
107
108 std::string SALOMEDSImpl_AttributeTableOfReal::GetTitle() const 
109 {
110   return myTitle;
111 }
112
113 void SALOMEDSImpl_AttributeTableOfReal::SetRowData(const int theRow,
114                                                    const std::vector<double>& theData) 
115 {
116   CheckLocked();  
117   if(theData.size() > myNbColumns) SetNbColumns(theData.size());
118
119   Backup();
120
121   while (myRows.size() < theRow) { // append new row titles
122     myRows.push_back(std::string(""));
123   }
124
125   int i, aShift = (theRow-1)*myNbColumns, aLength = theData.size();
126   for(i = 1; i <= aLength; i++) {
127     myTable[aShift + i] = theData[i-1];
128   }
129
130   if(theRow > myNbRows) myNbRows = theRow;
131   
132   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
133 }
134
135 std::vector<double> SALOMEDSImpl_AttributeTableOfReal::GetRowData(const int theRow)
136 {
137   std::vector<double> aSeq;
138   int i, aShift = (theRow-1)*myNbColumns;
139   for(i = 1; i <= myNbColumns; i++) {
140      if(myTable.find(aShift+i) != myTable.end()) 
141        aSeq.push_back(myTable[aShift+i]);
142      else
143        aSeq.push_back(0.);
144   }
145   
146   return aSeq;
147 }
148
149 void SALOMEDSImpl_AttributeTableOfReal::SetRowTitle(const int theRow,
150                                                     const std::string& theTitle) 
151 {
152   CheckLocked();  
153   Backup();
154   std::string aTitle(theTitle), aUnit = GetRowUnit(theRow);
155   if(aUnit.size()>0) {
156     aTitle += SEPARATOR;
157     aTitle += aUnit;
158   }
159   myRows[theRow-1] = aTitle;
160   
161   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
162 }
163
164 void SALOMEDSImpl_AttributeTableOfReal::SetRowUnit(const int theRow,
165                                                    const std::string& theUnit) 
166 {
167   CheckLocked();  
168   Backup();
169   std::string aTitle = GetRowTitle(theRow);
170   aTitle += SEPARATOR;
171   aTitle += theUnit;
172   
173   myRows[theRow-1] = aTitle;
174   
175   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
176 }
177
178 void SALOMEDSImpl_AttributeTableOfReal::SetRowUnits(const std::vector<std::string>& theUnits)
179 {
180   if (theUnits.size() != GetNbRows()) throw DFexception("Invalid number of rows");
181   int aLength = theUnits.size(), i;
182   for(i = 1; i <= aLength; i++) SetRowUnit(i, theUnits[i-1]);
183   
184   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
185 }
186
187 std::vector<std::string> SALOMEDSImpl_AttributeTableOfReal::GetRowUnits()
188 {
189   std::vector<std::string> aSeq;
190   int aLength = myRows.size(), i;
191   for(i=0; i<aLength; i++) aSeq.push_back(getUnit(myRows[i]));
192   return aSeq;
193 }
194
195 void SALOMEDSImpl_AttributeTableOfReal::SetRowTitles(const std::vector<std::string>& theTitles)
196 {
197   if (theTitles.size() != GetNbRows()) throw DFexception("Invalid number of rows");
198   int aLength = theTitles.size(), i;
199   for(i = 1; i <= aLength; i++) SetRowTitle(i, theTitles[i-1]);
200   
201   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
202 }
203
204 std::vector<std::string> SALOMEDSImpl_AttributeTableOfReal::GetRowTitles()
205 {
206   std::vector<std::string> aSeq;
207   int aLength = myRows.size(), i;
208   for(i=0; i<aLength; i++) aSeq.push_back(getTitle(myRows[i]));
209   return aSeq;
210 }
211
212 std::string SALOMEDSImpl_AttributeTableOfReal::GetRowTitle(const int theRow) const 
213 {
214   return getTitle(myRows[theRow-1]);
215 }
216
217
218 std::string SALOMEDSImpl_AttributeTableOfReal::GetRowUnit(const int theRow) const 
219 {
220   return getUnit(myRows[theRow-1]);
221 }
222
223 void SALOMEDSImpl_AttributeTableOfReal::SetColumnData(const int theColumn,
224                                                       const std::vector<double>& theData) 
225 {
226   CheckLocked();  
227   if(theColumn > myNbColumns) SetNbColumns(theColumn);
228
229   Backup();
230
231   int i, aLength = theData.size();
232   for(i = 1; i <= aLength; i++) {
233     myTable[myNbColumns*(i-1)+theColumn] = theData[i-1];
234   }
235
236   if(aLength > myNbRows) {
237     myNbRows = aLength;
238     while (myRows.size() < myNbRows) { // append empty row titles
239       myRows.push_back(std::string(""));
240     }
241   }
242   
243   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
244 }
245
246 std::vector<double> SALOMEDSImpl_AttributeTableOfReal::GetColumnData(const int theColumn)
247 {
248   std::vector<double> aSeq;
249   
250   int i, anIndex;
251   for(i = 1; i <= myNbRows; i++) {
252     anIndex = myNbColumns*(i-1) + theColumn;
253     if(myTable.find(anIndex) != myTable.end()) 
254       aSeq.push_back(myTable[anIndex]);
255     else
256       aSeq.push_back(0.);
257   }
258   
259   return aSeq;
260 }
261
262 void SALOMEDSImpl_AttributeTableOfReal::SetColumnTitle(const int theColumn,
263                                                        const std::string& theTitle) 
264 {
265   CheckLocked();  
266   Backup();
267   while(myCols.size() < theColumn) myCols.push_back(std::string(""));
268   myCols[theColumn-1] = theTitle;
269
270   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
271 }
272
273 std::string SALOMEDSImpl_AttributeTableOfReal::GetColumnTitle(const int theColumn) const 
274 {
275   if(myCols.empty()) return "";
276   if(myCols.size() < theColumn) return "";
277   return myCols[theColumn-1];
278 }
279
280 void SALOMEDSImpl_AttributeTableOfReal::SetColumnTitles(const std::vector<std::string>& theTitles)
281 {
282   if (theTitles.size() != myNbColumns) throw DFexception("Invalid number of columns");
283   int aLength = theTitles.size(), i;
284   for(i = 0; i < aLength; i++)  myCols[i] = theTitles[i];
285   
286   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
287 }
288
289 std::vector<std::string> SALOMEDSImpl_AttributeTableOfReal::GetColumnTitles()
290 {
291   std::vector<std::string> aSeq;
292   int aLength = myCols.size(), i;
293   for(i=0; i<aLength; i++) aSeq.push_back(myCols[i]);
294   return aSeq;
295 }
296
297 int SALOMEDSImpl_AttributeTableOfReal::GetNbRows() const
298 {
299   return myNbRows;
300 }
301
302 int SALOMEDSImpl_AttributeTableOfReal::GetNbColumns() const
303 {
304   return myNbColumns;
305 }
306
307 void SALOMEDSImpl_AttributeTableOfReal::PutValue(const double& theValue,
308                                                  const int theRow,
309                                                  const int theColumn) 
310 {
311   CheckLocked();      
312   //Backup();
313   if(theColumn > myNbColumns) SetNbColumns(theColumn);
314
315   int anIndex = (theRow-1)*myNbColumns + theColumn;
316   myTable[anIndex] =  theValue;
317
318   if(theRow > myNbRows) {
319     while (myRows.size() < theRow) { // append empty row titles
320       myRows.push_back(std::string(""));
321     }
322     myNbRows = theRow;
323   }
324   
325   SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved 
326 }
327
328 bool SALOMEDSImpl_AttributeTableOfReal::HasValue(const int theRow,
329                                                  const int theColumn) 
330 {
331   if(theRow > myNbRows || theRow < 1) return false;
332   if(theColumn > myNbColumns || theColumn < 1) return false;
333   int anIndex = (theRow-1)*myNbColumns + theColumn;
334   return (myTable.find(anIndex) != myTable.end()); 
335 }
336
337 double SALOMEDSImpl_AttributeTableOfReal::GetValue(const int theRow,
338                                                    const int theColumn) 
339 {
340   if(theRow > myNbRows || theRow < 1) throw DFexception("Invalid cell index");
341   if(theColumn > myNbColumns || theColumn < 1) throw DFexception("Invalid cell index");
342
343   int anIndex = (theRow-1)*myNbColumns + theColumn;
344   if(myTable.find(anIndex) != myTable.end()) return myTable[anIndex];
345   
346   throw DFexception("Invalid cell index");
347   return 0.;
348 }
349
350 void SALOMEDSImpl_AttributeTableOfReal::RemoveValue(const int theRow, const int theColumn)
351 {
352   CheckLocked();  
353   if(theRow > myNbRows || theRow < 1) throw DFexception("Invalid cell index");
354   if(theColumn > myNbColumns || theColumn < 1) throw DFexception("Invalid cell index");
355
356   int anIndex = (theRow-1)*myNbColumns + theColumn;
357   if (myTable.find(anIndex) != myTable.end()) {
358     //Backup();
359     myTable.erase(anIndex);
360     SetModifyFlag(); // table is modified
361   }
362 }
363
364 const std::string& SALOMEDSImpl_AttributeTableOfReal::ID() const
365 {
366   return GetID();
367 }
368
369 void SALOMEDSImpl_AttributeTableOfReal::Restore(DF_Attribute* with) 
370 {
371   int anIndex;
372   SALOMEDSImpl_AttributeTableOfReal* aTable = dynamic_cast<SALOMEDSImpl_AttributeTableOfReal*>(with);
373   if(!aTable) throw DFexception("Can't Restore from a null attribute");
374
375   myTable.clear();
376   myCols.clear();
377   myRows.clear();
378
379   myTable = aTable->myTable;
380   myNbRows = aTable->myNbRows;
381   myNbColumns = aTable->myNbColumns;
382   myTitle = aTable->myTitle;
383   
384   for(anIndex = 1; anIndex <= aTable->GetNbRows();anIndex++)
385     myRows.push_back(aTable->GetRowTitle(anIndex));
386
387   for(anIndex = 1; anIndex <= aTable->GetNbColumns(); anIndex++) 
388     myCols.push_back(aTable->GetColumnTitle(anIndex));
389 }
390
391 DF_Attribute* SALOMEDSImpl_AttributeTableOfReal::NewEmpty() const
392 {
393   return new SALOMEDSImpl_AttributeTableOfReal();
394 }
395
396 void SALOMEDSImpl_AttributeTableOfReal::Paste(DF_Attribute* into)
397 {
398   int anIndex;
399   SALOMEDSImpl_AttributeTableOfReal* aTable = dynamic_cast<SALOMEDSImpl_AttributeTableOfReal*>(into);
400   if(!aTable) throw DFexception("Can't Paste into a null attribute"); 
401
402   aTable->myTable.clear();
403   aTable->myCols.clear();
404   aTable->myRows.clear();
405
406   aTable->myTable = myTable;
407   aTable->myTitle = myTitle;
408   aTable->myNbRows = myNbRows;
409   aTable->myNbColumns = myNbColumns;
410
411   for(anIndex = 1; anIndex <= GetNbRows();anIndex++)
412     aTable->myRows.push_back(GetRowTitle(anIndex));
413   for(anIndex = 1; anIndex <= GetNbColumns(); anIndex++) 
414     aTable->myCols.push_back(GetColumnTitle(anIndex));
415 }
416
417 std::vector<int> SALOMEDSImpl_AttributeTableOfReal::GetSetRowIndices(const int theRow)
418 {
419   std::vector<int> aSeq;
420
421   int i, aShift = myNbColumns*(theRow-1);
422   for(i = 1; i <= myNbColumns; i++) {
423     if(myTable.find(aShift + i) != myTable.end()) aSeq.push_back(i);
424   }
425   
426   return aSeq;
427 }
428
429 std::vector<int> SALOMEDSImpl_AttributeTableOfReal::GetSetColumnIndices(const int theColumn)
430 {
431   std::vector<int> aSeq;
432
433   int i, anIndex;
434   for(i = 1; i <= myNbRows; i++) {
435     anIndex = myNbColumns*(i-1)+theColumn;
436     if(myTable.find(anIndex) != myTable.end()) aSeq.push_back(i);
437   }
438   
439   return aSeq;
440 }
441
442 std::string SALOMEDSImpl_AttributeTableOfReal::Save() 
443 {
444   std::string aString;
445   char* buffer = new char[1024];
446   int i, j, l;
447
448   //Title
449   l = myTitle.size();
450   sprintf(buffer, "%d\n", l);
451   aString+=buffer;
452   for(i=0; i<l; i++) {
453     aString += myTitle[i];
454     aString +='\n';
455   }
456   
457   //Nb rows
458   sprintf(buffer, "%d\n", myNbRows);
459   aString+=buffer;
460
461   //Row titles
462   for(i=0; i<myNbRows; i++) {
463     l = myRows[i].size();
464     sprintf(buffer, "%d\n", l);
465     aString+=buffer;
466     for(j=0; j<l; j++) {
467       aString += myRows[i][j];
468       aString += '\n';
469     }
470   }  
471
472   //Nb columns
473   sprintf(buffer, "%d\n", myNbColumns);
474   aString+=buffer;
475
476   //Columns titles
477   for(i=0; i<myNbColumns; i++) {
478     l = myCols[i].size();
479     sprintf(buffer, "%d\n", l);
480     aString+=buffer;
481     for(j=0; j<l; j++) {
482       aString += myCols[i][j];
483       aString += '\n';
484     }
485   }
486
487   //Store the table values
488   l = myTable.size();
489   sprintf(buffer, "%d\n", l);
490   aString+=buffer;
491   for(MI p = myTable.begin(); p != myTable.end(); p++) {
492     sprintf(buffer, "%d\n%.64e\n", p->first, p->second);
493     aString += buffer;
494   }
495
496   delete []buffer;
497   return aString;
498 }
499
500 void SALOMEDSImpl_AttributeTableOfReal::Load(const std::string& value) 
501 {
502   std::vector<std::string> v;
503   int i,  j, l, pos, aSize = (int)value.size(); 
504   for(i = 0, pos = 0; i<aSize; i++) {
505     if(value[i] == '\n') {
506        v.push_back(value.substr(pos, i-pos));
507        pos = i+1;
508     }
509   }
510
511   Backup();
512
513   pos = 0;
514   std::string aStr;
515
516   //Title
517   l = strtol(v[pos++].c_str(), NULL, 10);
518
519   myTitle = std::string(l, 0);
520   for(i=0; i<l; i++) {
521     myTitle[i] = v[pos++][0];
522   }
523
524   //Nb rows
525   myNbRows = strtol(v[pos++].c_str(), NULL, 10);
526
527   //Rows titles
528   myRows.clear();  
529   for(i=1; i<=myNbRows; i++) { 
530     l = strtol(v[pos++].c_str(), NULL, 10);
531     aStr = std::string(l,0);
532     for(j=0; j<l; j++) {
533       aStr[j] = v[pos++][0];
534     }
535     myRows.push_back(aStr);
536   }
537
538   //Nb columns
539   myNbColumns = strtol(v[pos++].c_str(), NULL, 10);
540
541   //Columns titles
542   myCols.clear();
543   for(i=1; i<=myNbColumns; i++) {
544     l = strtol(v[pos++].c_str(), NULL, 10);
545     aStr = std::string(l,0);
546     for(j=0; j<l; j++) {
547       aStr[j] = v[pos++][0];
548     }
549     myCols.push_back(aStr);
550   }
551
552   //Restore the table values
553   l = strtol(v[pos++].c_str(), NULL, 10);
554   myTable.clear();
555   for(i=1; i<=l; i++) {
556     int aKey = strtol(v[pos++].c_str(), NULL, 10);
557     double aValue = strtod(v[pos++].c_str(), NULL);
558     myTable[aKey] = aValue;
559   }
560
561 }
562
563 std::vector<int> SALOMEDSImpl_AttributeTableOfReal::SortRow(const int theRow, SortOrder sortOrder, SortPolicy sortPolicy )
564 {
565   CheckLocked();  
566   std::vector<int> result;
567   if ( theRow > 0 && theRow <= myNbRows ) {
568     std::vector<int> indices( myNbColumns );
569     int cnt = 0;
570     for ( int i = 0; i < myNbColumns; i++ ) {
571       if ( sortPolicy != EmptyIgnore || HasValue(theRow, i+1) ) {
572         indices[cnt++] = i+1;
573       }
574     }
575     indices.resize(cnt);
576     
577     TableSorter<SALOMEDSImpl_AttributeTableOfReal> sorter( this, sortOrder, sortPolicy, theRow, true );
578     std::stable_sort( indices.begin(), indices.end(), sorter );
579
580     if ( sortPolicy == EmptyIgnore ) {
581       std::vector<int> other( myNbColumns );
582       cnt = 0;
583       for( int i = 0; i < myNbColumns; i++ )
584         other[i] = HasValue(theRow, i+1) ? indices[cnt++] : i+1;
585       indices = other;
586     }
587     result = indices;
588
589     for ( int col = 0; col < indices.size(); col++ ) {
590       int idx = indices[col];
591       if ( col+1 == idx ) continue;
592       SwapCells(theRow, col+1, theRow, idx);
593       int idx1 = 0;
594       for ( int i = col+1; i < indices.size() && idx1 == 0; i++)
595         if ( indices[i] == col+1 ) idx1 = i;
596       indices[idx1] = idx;
597     }
598     // no need for SetModifyFlag(), since it is done by SwapCells()
599   }
600   return result;
601 }
602
603 std::vector<int> SALOMEDSImpl_AttributeTableOfReal::SortColumn(const int theColumn, SortOrder sortOrder, SortPolicy sortPolicy )
604 {
605   CheckLocked();  
606   std::vector<int> result;
607   if ( theColumn > 0 && theColumn <= myNbColumns ) {
608     std::vector<int> indices( myNbRows );
609     int cnt = 0;
610     for ( int i = 0; i < myNbRows; i++ ) {
611       if ( sortPolicy != EmptyIgnore || HasValue(i+1, theColumn) ) {
612         indices[cnt++] = i+1;
613       }
614     }
615     indices.resize(cnt);
616     
617     TableSorter<SALOMEDSImpl_AttributeTableOfReal> sorter( this, sortOrder, sortPolicy, theColumn, false );
618     std::stable_sort( indices.begin(), indices.end(), sorter );
619
620     if ( sortPolicy == EmptyIgnore ) {
621       std::vector<int> other( myNbRows );
622       cnt = 0;
623       for( int i = 0; i < myNbRows; i++ )
624         other[i] = HasValue(i+1, theColumn) ? indices[cnt++] : i+1;
625       indices = other;
626     }
627     result = indices;
628
629     for ( int row = 0; row < indices.size(); row++ ) {
630       int idx = indices[row];
631       if ( row+1 == idx ) continue;
632       SwapCells(row+1, theColumn, idx, theColumn);
633       int idx1 = 0;
634       for ( int i = row+1; i < indices.size() && idx1 == 0; i++)
635         if ( indices[i] == row+1 ) idx1 = i;
636       indices[idx1] = idx;
637     }
638     // no need for SetModifyFlag(), since it is done by SwapCells()
639   }
640   return result;
641 }
642
643 std::vector<int> SALOMEDSImpl_AttributeTableOfReal::SortByRow(const int theRow, SortOrder sortOrder, SortPolicy sortPolicy )
644 {
645   CheckLocked();  
646   std::vector<int> result;
647   if ( theRow > 0 && theRow <= myNbRows ) {
648     std::vector<int> indices( myNbColumns );
649     int cnt = 0;
650     for ( int i = 0; i < myNbColumns; i++ ) {
651       if ( sortPolicy != EmptyIgnore || HasValue(theRow, i+1) ) {
652         indices[cnt++] = i+1;
653       }
654     }
655     indices.resize(cnt);
656     
657     TableSorter<SALOMEDSImpl_AttributeTableOfReal> sorter( this, sortOrder, sortPolicy, theRow, true );
658     std::stable_sort( indices.begin(), indices.end(), sorter );
659
660     if ( sortPolicy == EmptyIgnore ) {
661       std::vector<int> other( myNbColumns );
662       cnt = 0;
663       for( int i = 0; i < myNbColumns; i++ )
664         other[i] = HasValue(theRow, i+1) ? indices[cnt++] : i+1;
665       indices = other;
666     }
667     result = indices;
668
669     for ( int col = 0; col < indices.size(); col++ ) {
670       int idx = indices[col];
671       if ( col+1 == idx ) continue;
672       SwapColumns(col+1, idx);
673       int idx1 = 0;
674       for ( int i = col+1; i < indices.size() && idx1 == 0; i++)
675         if ( indices[i] == col+1 ) idx1 = i;
676       indices[idx1] = idx;
677     }
678     // no need for SetModifyFlag(), since it is done by SwapColumns()
679   }
680   return result;
681 }
682
683 std::vector<int> SALOMEDSImpl_AttributeTableOfReal::SortByColumn(const int theColumn, SortOrder sortOrder, SortPolicy sortPolicy )
684 {
685   CheckLocked();  
686   std::vector<int> result;
687   if ( theColumn > 0 && theColumn <= myNbColumns ) {
688     std::vector<int> indices( myNbRows );
689     int cnt = 0;
690     for ( int i = 0; i < myNbRows; i++ ) {
691       if ( sortPolicy != EmptyIgnore || HasValue(i+1, theColumn) ) {
692         indices[cnt++] = i+1;
693       }
694     }
695     indices.resize(cnt);
696     
697     TableSorter<SALOMEDSImpl_AttributeTableOfReal> sorter( this, sortOrder, sortPolicy, theColumn, false );
698     std::stable_sort( indices.begin(), indices.end(), sorter );
699
700     if ( sortPolicy == EmptyIgnore ) {
701       std::vector<int> other( myNbRows );
702       cnt = 0;
703       for( int i = 0; i < myNbRows; i++ )
704         other[i] = HasValue(i+1, theColumn) ? indices[cnt++] : i+1;
705       indices = other;
706     }
707     result = indices;
708
709     for ( int row = 0; row < indices.size(); row++ ) {
710       int idx = indices[row];
711       if ( row+1 == idx ) continue;
712       SwapRows(row+1, idx);
713       int idx1 = 0;
714       for ( int i = row+1; i < indices.size() && idx1 == 0; i++)
715         if ( indices[i] == row+1 ) idx1 = i;
716       indices[idx1] = idx;
717     }
718     // no need for SetModifyFlag(), since it is done by SwapRows()
719   }
720   return result;
721 }
722
723 void SALOMEDSImpl_AttributeTableOfReal::SwapCells(const int theRow1, const int theColumn1, 
724                                                   const int theRow2, const int theColumn2)
725 {
726   CheckLocked();  
727   if (theRow1    > myNbRows    || theRow1 < 1)    throw DFexception("Invalid cell index");
728   if (theRow2    > myNbRows    || theRow2 < 1)    throw DFexception("Invalid cell index");
729   if (theColumn1 > myNbColumns || theColumn1 < 1) throw DFexception("Invalid cell index");
730   if (theColumn2 > myNbColumns || theColumn2 < 1) throw DFexception("Invalid cell index");
731
732   int anIndex1 = (theRow1-1)*myNbColumns + theColumn1;
733   int anIndex2 = (theRow2-1)*myNbColumns + theColumn2;
734
735   bool hasValue1 = myTable.find(anIndex1) != myTable.end();
736   bool hasValue2 = myTable.find(anIndex2) != myTable.end();
737
738   if (!hasValue1 && !hasValue2) return;                   // nothing changed
739
740   double value1  = hasValue1 ? myTable[anIndex1] : 0;
741   double value2  = hasValue2 ? myTable[anIndex2] : 0;
742
743   if (hasValue1 && hasValue2 && value1 == value2) return; // nothing changed
744
745   if (hasValue1) myTable[anIndex2] = value1;
746   else           myTable.erase(anIndex2);
747   if (hasValue2) myTable[anIndex1] = value2;
748   else           myTable.erase(anIndex1);
749
750   SetModifyFlag(); // table is modified
751 }
752
753 void SALOMEDSImpl_AttributeTableOfReal::SwapRows(const int theRow1, const int theRow2)
754 {
755   CheckLocked();  
756   for (int i = 1; i <= myNbColumns; i++)
757     SwapCells(theRow1, i, theRow2, i);
758   // swap row titles
759   std::string tmp = myRows[theRow1-1];
760   myRows[theRow1-1] = myRows[theRow2-1];
761   myRows[theRow2-1] = tmp;
762   // no need for SetModifyFlag(), since it is done by SwapCells()
763 }
764
765 void SALOMEDSImpl_AttributeTableOfReal::SwapColumns(const int theColumn1, const int theColumn2)
766 {
767   CheckLocked();  
768   for (int i = 1; i <= myNbRows; i++)
769     SwapCells(i, theColumn1, i, theColumn2);
770   // swap column titles
771   std::string tmp = myCols[theColumn1-1];
772   myCols[theColumn1-1] = myCols[theColumn2-1];
773   myCols[theColumn2-1] = tmp;
774   // no need for SetModifyFlag(), since it is done by SwapCells()
775 }
776