source: orange/source/orange/table.cpp @ 11048:782c9d850e72

Revision 11048:782c9d850e72, 21.9 KB checked in by Ales Erjavec <ales.erjavec@…>, 16 months ago (diff)

Fixed 'TExampleTable.clone' method (erroneous copy constructor for TExampleTable).

The 'clone' method calls the C++ copy constructor to copy the table,
but the default copy constructor fails to properly copy the instances
(both tables end up claiming ownership of the same memory space).

Fixed by implementing a copy constructor to make a deep copy of
the instances.

Fixes #1260

Line 
1/*
2    This file is part of Orange.
3   
4    Copyright 1996-2010 Faculty of Computer and Information Science, University of Ljubljana
5    Contact: janez.demsar@fri.uni-lj.si
6
7    Orange is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11
12    Orange is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with Orange.  If not, see <http://www.gnu.org/licenses/>.
19*/
20
21
22#include "random.hpp"
23#include "vars.hpp"
24#include "domain.hpp"
25#include "domaindepot.hpp"
26#include "filter.hpp"
27#include "distvars.hpp"
28#include "stladdon.hpp"
29
30#include "crc.h"
31
32#include "table.ppp"
33
34
35TExampleTable::TExampleTable(const TExampleTable& orig)
36: TExampleGenerator(orig.domain),
37  examples(NULL),
38  _Last(NULL),
39  _EndSpace(NULL),
40  ownsExamples(true)
41{
42  reserve(orig.size());
43  for(int i = 0; i < orig.size(); ++i){
44      push_back(new TExample(orig.at(i)));
45  }
46}
47
48TExampleTable::TExampleTable(PDomain dom, bool owns)
49: TExampleGenerator(dom),
50  examples(NULL),
51  _Last(NULL),
52  _EndSpace(NULL),
53  ownsExamples(owns)
54{ version = ++generatorVersion; }
55
56
57/* Careful: the meaning of 'owns' is the opposite of what we have
58   in Python: if owns==true, then the table doesn't hold only the
59   references to examples (in another table) but has its own examples! */
60TExampleTable::TExampleTable(PExampleGenerator gen, bool owns)
61: TExampleGenerator(gen->domain),
62  examples(NULL),
63  _Last(NULL),
64  _EndSpace(NULL),
65  ownsExamples(owns)
66{ 
67  if (!ownsExamples) {
68    lock = fixedExamples(gen);
69    addExamples(lock);
70  }
71  else
72    addExamples(gen);
73}
74
75
76TExampleTable::TExampleTable(PDomain dom, PExampleGenerator gen, bool filterMetas)
77: TExampleGenerator(dom),
78  examples(NULL),
79  _Last(NULL),
80  _EndSpace(NULL),
81  ownsExamples(true)
82{ 
83  addExamples(gen, filterMetas);
84}
85
86
87TExampleTable::TExampleTable(PExampleGenerator alock, int)
88: TExampleGenerator(alock ? alock->domain : PDomain()),
89  examples(NULL),
90  _Last(NULL),
91  _EndSpace(NULL),
92  ownsExamples(false),
93  lock(alock)
94{ 
95  version = ++generatorVersion;
96}
97
98
99TExampleTable::TExampleTable(PExampleGeneratorList tables)
100: TExampleGenerator(PDomain()),
101  examples(NULL),
102  _Last(NULL),
103  _EndSpace(NULL),
104  ownsExamples(true),
105  lock()
106{
107  if (!tables->size())
108    raiseError("merging constructor was given no datasets to merge");
109
110  TDomainList domains;
111  int size = tables->front()->numberOfExamples();
112  vector<TExampleIterator> iterators;
113  PITERATE(TExampleGeneratorList, sdi, tables) {
114    if ((*sdi)->numberOfExamples() != size)
115      raiseError("cannot merge dataset of unequal sizes");
116    domains.push_back((*sdi)->domain);
117    iterators.push_back((*sdi)->begin());
118  }
119
120  TDomainMultiMapping mapping;
121  domain = combineDomains(PDomainList(domains), mapping);
122
123  int exno = 0;
124  for(; iterators.front(); exno++) {
125    TExample *example = mlnew TExample(domain);
126    addExample(example);
127    TDomainMultiMapping::const_iterator dmmi(mapping.begin());
128    TExample::iterator ei(example->begin()), ee(example->end());
129    TVarList::const_iterator vi(domain->variables->begin());
130    for(; ei!=ee; ei++, dmmi++, vi++) {
131      bool notfirst = 0;
132      for(vector<pair<int, int> >::const_iterator sdmmi((*dmmi).begin()), sdmme((*dmmi).end()); sdmmi!=sdmme; sdmmi++) {
133        if (!mergeTwoValues(*ei, (*iterators[(*sdmmi).first])[(*sdmmi).second], notfirst++ != 0))
134          raiseError("mismatching value of attribute '%s' in example #%i", (*vi)->get_name().c_str(), exno);
135      }
136    }
137
138    // copy meta attributes and increase the iterators
139    for(vector<TExampleIterator>::iterator ii(iterators.begin()), ie(iterators.end()); ii!=ie; ++*(ii++)) {
140      ITERATE(TMetaValues, mvi, (**ii).meta) {
141        if (example->hasMeta((*mvi).first)) {
142          if (!mergeTwoValues(example->getMeta((*mvi).first), (*mvi).second, true)) {
143            PVariable metavar = domain->getMetaVar((*mvi).first, false);
144            if (metavar && metavar->get_name().length())
145              raiseError("Meta attribute '%s' has ambiguous values on example #%i", metavar->get_name().c_str(), exno);
146            else
147              raiseError("Meta attribute %i has ambiguous values on example #%i", (*mvi).first, exno);
148          }
149        }
150        else
151          example->setMeta((*mvi).first, (*mvi).second);
152      }
153    }
154  }
155
156  version = ++generatorVersion;
157}
158
159
160TExampleTable::~TExampleTable()
161{ 
162  if (examples) {
163    if (ownsExamples)
164      for(TExample **t = examples; t != _Last; )
165        delete *(t++);
166    free(examples);
167  }
168}
169
170
171int TExampleTable::traverse(visitproc visit, void *arg) const
172{ 
173  TRAVERSE(TExampleGenerator::traverse);
174  if (ownsExamples)
175    for(TExample **ee = examples; ee != _Last; ee++)
176      TRAVERSE((*ee)->traverse)
177
178  return 0;
179}
180
181
182int TExampleTable::dropReferences() 
183{ 
184  DROPREFERENCES(TExampleGenerator::dropReferences);
185  clear();
186  return 0;
187}
188
189
190void TExampleTable::reserve(const int &i)
191{ 
192  if (!examples) {
193    if (i) {
194      examples = (TExample **)malloc(i * sizeof(TExample *));
195      _Last = examples;
196      _EndSpace = examples + i;
197    }
198    else {
199      _Last = _EndSpace = examples;
200    }
201  }
202
203  else {
204    if (!i) {
205      if (examples) {
206        if (_Last == examples) {
207          free(examples);
208          _Last = _EndSpace = examples = NULL;
209        }
210        // else do nothing: reserve should not remove examples!
211      }
212      else {
213        _Last = _EndSpace = examples;
214      }
215    }
216    else {
217      if (i>_Last - examples) {
218        int lastofs = _Last - examples;
219        TExample **newexamples = (TExample **)realloc(examples, i * sizeof(TExample));
220        if (!newexamples)
221          raiseErrorWho("resize", "out of memory");
222        examples = newexamples;
223        _Last = examples + lastofs;
224        _EndSpace = examples + i;
225      }
226      // else do nothing: i is too small and reserve should not remove examples!
227    }
228  }
229}
230
231
232void TExampleTable::growTable()
233{
234  reserve(!examples ? 256 : int(1.25 * (_EndSpace - examples)));
235}
236
237
238void TExampleTable::shrinkTable()
239{
240  if (_Last == examples)
241    reserve(0);
242  else {
243    int sze = int(1.25 * (_Last-examples));
244    if (sze < 256)
245      sze = 256;
246    if (sze < _EndSpace - examples)
247      reserve(sze);
248  }
249}
250
251
252TExample &TExampleTable::at(const int &i)
253{
254  if (_Last == examples)
255    raiseError("no examples");
256  if ((i<0) || (i >= _Last-examples))
257    raiseError("index %i out of range 0-%i", i, _Last-examples-1);
258
259  return *examples[i];
260}
261
262
263const TExample &TExampleTable::at(const int &i) const
264{
265  if (_Last == examples)
266    raiseError("no examples");
267  if ((i<0) || (i >= _Last-examples))
268    raiseError("index %i out of range 0-%i", i, _Last-examples-1);
269
270  return *examples[i];
271}
272
273
274TExample &TExampleTable::back() 
275{
276  if (_Last == examples)
277    raiseError("no examples");
278
279  return *_Last[-1];
280}
281
282
283const TExample &TExampleTable::back() const
284{
285  if (_Last == examples)
286    raiseError("no examples");
287
288  return *_Last[-1];
289}
290
291
292void TExampleTable::clear()
293{
294  if (examples) {
295    if (ownsExamples)
296      while (_Last != examples)
297        delete *--_Last;
298    free(examples);
299  }
300  _Last = _EndSpace = examples = NULL;
301  examplesHaveChanged();
302}
303
304
305bool TExampleTable::empty() const
306{ 
307  return (_Last == examples);
308}
309
310
311TExample &TExampleTable::front() 
312{
313  if (_Last == examples)
314    raiseError("no examples");
315
316  return **examples;
317}
318
319
320const TExample &TExampleTable::front() const
321{
322  if (_Last == examples)
323    raiseError("no examples");
324
325  return **examples;
326}
327
328
329TExample &TExampleTable::operator[](const int &i)
330{
331  return *examples[i];
332}
333
334
335const TExample &TExampleTable::operator[](const int &i) const
336{
337  return *examples[i];
338}
339
340
341void TExampleTable::push_back(TExample *x)
342{
343  if (_Last == _EndSpace)
344    growTable();
345  *(_Last++) = x;
346
347  examplesHaveChanged();
348}
349
350
351TExample &TExampleTable::new_example()
352{
353  TExample *x = mlnew TExample(domain);
354  push_back(x);
355  return *x;
356}
357
358
359void TExampleTable::delete_last()
360{ if (_Last == examples)
361    raiseError("no examples");
362  erase(_Last-1);
363}
364
365
366int TExampleTable::size() const
367{
368  return examples ? _Last - examples : 0;
369}
370
371
372void TExampleTable::erase(const int &sti)
373{
374  if (_Last == examples)
375    raiseError("no examples");
376  if (sti >= _Last-examples)
377    raiseError("index %i out of range 0-%i", sti, _Last-examples-1);
378  erase(examples + sti);
379}
380
381
382void TExampleTable::erase(const int &sti, const int &eni)
383{
384  if (_Last == examples)
385    raiseError("no examples");
386  if (sti >= _Last-examples)
387    raiseError("index %i out of range 0-%i", sti, _Last-examples-1);
388  erase(examples + sti, examples + eni);
389}
390
391
392void TExampleTable::erase(TExample **ptr)
393{
394  if (ownsExamples)
395    delete *ptr;
396  memmove(ptr, ptr+1, sizeof(TExample **)*(_Last - ptr - 1));
397  _Last--;
398  examplesHaveChanged();
399}
400
401
402void TExampleTable::erase(TExample **fromPtr, TExample **toPtr)
403{
404  if (ownsExamples) {
405    TExample **ee = fromPtr;
406    while (ee != toPtr)
407      delete *(ee++);
408  }
409
410  memmove(fromPtr, toPtr, sizeof(TExample **)*(_Last - toPtr));
411
412  _Last -= (toPtr - fromPtr);
413
414  shrinkTable();
415  examplesHaveChanged();
416}
417
418
419void TExampleTable::insert(const int &sti, const TExample &ex)
420{
421  if (ex.domain != domain)
422    raiseError("examples has invalid domain (ExampleTable.insert doesn't convert)");
423  if (sti > _Last-examples)
424    raiseError("index %i out of range 0-%i", sti, _Last-examples);
425 
426  if (_Last == _EndSpace)
427    growTable();
428
429  TExample **sp = examples + sti;
430  memmove(sp+1, sp, sizeof(TExample **)*(_Last - sp));
431  *sp = ownsExamples ? CLONE(TExample, &ex) : const_cast<TExample *>(&ex);
432  _Last++;
433
434  examplesHaveChanged();
435}
436
437
438TExampleIterator TExampleTable::begin()
439{
440  return TExampleIterator(this, examples ? *examples : NULL, (void *)examples);
441}
442
443
444void TExampleTable::copyIterator(const TExampleIterator &src, TExampleIterator &dest)
445{ 
446  TExampleGenerator::copyIterator(src, dest);
447  dest.data = src.data;
448}
449
450
451void TExampleTable::increaseIterator(TExampleIterator &it)
452{
453  if (++((TExample **&)(it.data)) == _Last)
454    deleteIterator(it);
455  else
456    it.example = *(TExample **)(it.data);
457}
458
459
460bool TExampleTable::sameIterators(const TExampleIterator &i1, const TExampleIterator &i2)
461{
462  return (i1.data==i2.data);
463}
464
465
466bool TExampleTable::remove(TExampleIterator &it)
467{
468  erase( (TExample **)it.data );
469  examplesHaveChanged();
470  return true;
471}
472
473
474bool TExampleTable::randomExample(TExample &ex)
475{
476  if (!randomGenerator)
477    randomGenerator = mlnew TRandomGenerator();
478
479  if (!size())
480    return 0;
481  ex = operator[](randomGenerator->randint(size()));
482  return true;
483}
484
485
486/*  Searches for the example in the table and returns its class, if found. If there are more
487    different classes, it raises an exception, if example has no DK's, or returns DK otherwise.
488    If there's no corresponding example, it returns DK.
489    IN FUTURE: This method should return distributed values if more answers are possible.
490*/
491TValue TExampleTable::operator ()(const TExample &exam)
492{
493  if (empty())
494    return domain->classVar->DK();
495  TExample cexam(exam);
496  cexam.setClass(domain->classVar->DK());
497
498  bool hasValue = false;
499  TValue toret;
500  for(TExample **ri = examples; ri!=_Last; ri++)
501    if (cexam.compatible(**ri)) {
502      if (!hasValue) {
503        hasValue = true;
504        toret = (**ri).getClass(); 
505      }
506      else if (!toret.compatible((**ri).getClass())) {
507        // returns DK if the query contains specials, raises an exception otherwise
508        int Na = domain->attributes->size();
509        for(TExample::iterator vi(cexam.begin()); !((*vi).isSpecial()) && --Na; ++vi);
510        if (Na)
511          return domain->classVar->DK();
512        else
513          raiseError("ambiguous example (cannot determine the class value)");
514      }
515    }
516  return hasValue ? toret : domain->classVar->DK();
517}
518
519
520int TExampleTable::numberOfExamples()
521{
522  return size();
523}
524
525
526float TExampleTable::weightOfExamples(const int &weightID) const
527{
528  float weight = 0;
529  for(TExample **ri = examples; ri != _Last; ri++)
530    weight += WEIGHT(**ri);
531  return weight;
532}
533
534
535void TExampleTable::addExample(const TExample &example, bool filterMetas)
536{
537  if (ownsExamples)
538    if (example.domain == domain)
539      push_back(CLONE(TExample, &example));
540    else
541      push_back(mlnew TExample(domain, example, !filterMetas));
542  else
543    if (example.domain == domain)
544      push_back(const_cast<TExample *>(&example));
545    else
546      raiseError("domain mismatch (cannot convert a reference to example)");
547
548  examplesHaveChanged();
549}
550
551
552void TExampleTable::addExample(TExample *example)
553{
554  if (example->domain != domain)
555    raiseError("cannot add pointers to examples of different domains");
556  push_back(example);
557  examplesHaveChanged();
558}
559
560void TExampleTable::addExamples(PExampleGenerator gen, bool filterMetas)
561{
562  if (ownsExamples)
563    if (gen->domain == domain)
564      PEITERATE(ei, gen)
565        push_back(CLONE(TExample, &*ei)); 
566    else
567      PEITERATE(ei, gen)
568        push_back(mlnew TExample(domain, *ei, !filterMetas)); 
569
570  else {
571    if (gen->domain == domain)
572      PEITERATE(ei, gen)
573        push_back(&*ei); 
574    else
575      raiseError("domain mismatch (cannot convert a reference to example)");
576  }
577
578  examplesHaveChanged();
579}
580
581
582bool TExampleTable::removeExamples(TFilter &filter)
583{ 
584  TExample **ri = examples, **ci;
585  for( ; (ri!=_Last) && !filter(**ri); ri++);
586  if ((ci=ri)==_Last)
587    return 0;
588
589  while(++ri!=_Last)
590    if (!filter(**ri)) {
591      if (ownsExamples)
592        delete *ci;
593      **(ci++) = **ri;
594    }
595  erase(ci, _Last);
596
597  examplesHaveChanged();
598  return 1;
599}
600
601
602bool TExampleTable::removeExample(TExample &exam)
603{ // 'filter' dies before 'exam' and may contain a wrapped reference
604  TFilter_sameExample filter = TFilter_sameExample(PExample(exam));
605  return removeExamples(filter);
606}
607
608
609bool TExampleTable::removeCompatible(TExample &exam)
610{ // 'filter' dies before 'exam' and may contain a wrapped reference
611  TFilter_compatibleExample filter = TFilter_compatibleExample(PExample(exam));
612  return removeExamples(filter);
613}
614
615
616class TExI {
617public:
618  TExample *example;
619  int i;
620 
621  TExI(TExample *ex = NULL, const int ii=0)
622  : example(ex),
623    i(ii)
624  {}
625};
626
627
628bool lesstexi(const TExI &a, const TExI &b)
629{ return *a.example < *b.example; }
630
631
632void TExampleTable::removeDuplicates(const int &weightID)
633{ 
634  if (empty())
635    return;
636
637  vector<TExI> exi(_Last - examples);
638  int i = 0;
639  for(TExample **ep = examples; ep!=_Last; exi[i] = TExI(*(ep++), i), i++);
640  stable_sort(exi.begin(), exi.end(), lesstexi);
641
642  bool removed = false;
643  vector<TExI>::iterator fromPtr(exi.begin()), toPtr(fromPtr), ePtr(exi.end()); 
644  while(++fromPtr != ePtr) {
645    if (*(*fromPtr).example == *(*toPtr).example) {
646      if (weightID)
647        (*(*toPtr).example)[weightID].floatV += WEIGHT(*(*fromPtr).example);
648      if (ownsExamples)
649        delete examples[(*fromPtr).i];
650      examples[(*fromPtr).i] = NULL;
651      removed = true;
652    }
653    else
654      toPtr = fromPtr;
655  }
656
657  if (!removed)
658    return;
659
660  TExample **fromE = examples;
661  while (*fromE) // do not need to check !=_Last; there is a null pointer somewhere
662    fromE++;
663
664  TExample **toE = fromE++; // toE points to the next free spot
665  for(; fromE != _Last; fromE++)
666    if (*fromE)
667      *toE++ = *fromE;
668
669  _Last = toE;
670
671  shrinkTable();
672  examplesHaveChanged();
673}
674
675
676// Changes the domain and converts all the examples.
677void TExampleTable::changeDomain(PDomain dom, bool filterMetas)
678{
679  domain = dom;
680  if (ownsExamples)
681    for (TExample **ri = examples; ri!=_Last; ri++) {
682      TExample *tmp = mlnew TExample(dom, **ri, !filterMetas);
683      delete *ri;
684      *ri = tmp;
685    }
686
687  else {
688    for (TExample **ri = examples; ri!=_Last; ri++)
689      *ri = mlnew TExample(dom, **ri, !filterMetas);
690    ownsExamples = false;
691    lock = PExampleGenerator();
692  }
693
694  examplesHaveChanged();
695}
696
697
698void TExampleTable::pickClass(PVariable classVar)
699{
700    if (!ownsExamples) {
701        raiseError("Cannot change the class in a table of references");
702    }
703    const int attrs = domain->attributes->size();
704    const int classes = domain->classVars->size();
705    TDomain *newDomain;
706    int classPos;
707    int end_off = 0;
708    if (!classVar) {
709        if (!classes) {
710            return;
711        }
712        end_off = -1;
713        newDomain = mlnew TDomain(classVar, domain->attributes.getReference()); // No class
714        newDomain->classVars->push_back(domain->classVar);
715        PITERATE(TVarList, ci, domain->classVars) {
716            if (*ci != classVar) {
717                newDomain->classVars->push_back(*ci);
718            }
719        }
720        classPos = attrs;
721    }
722    else {
723        classPos = attrs;
724        if (domain->classVar) {
725            classPos += 1;
726        }
727        else {
728            end_off += 1;
729        }
730        TVarList::const_iterator mci(domain->classVars->begin()), mce(domain->classVars->end());
731        for(; (mci != mce) && (*mci != classVar); ++mci, ++classPos);
732        if (mci == mce) {
733            raiseError("Domain has no class %s", classVar->get_name().c_str());
734        }
735        newDomain = mlnew TDomain(classVar, domain->attributes.getReference());
736        newDomain->classVars = mlnew TVarList();
737        TVarList::iterator ci(domain->classVars->begin());
738        TVarList::const_iterator const ce(domain->classVars->end());
739        if (!domain->classVar && (classPos != attrs)) {
740            ci++;
741        }
742        for(; ci != ce; ci++) {
743            if (*ci == classVar) {
744                if (domain->classVar) {
745                    newDomain->classVars->push_back(domain->classVar);
746                }
747                else if (classPos != attrs) {
748                    newDomain->classVars->push_back(domain->classVars->front());
749                }
750            }
751            else {
752                newDomain->classVars->push_back(*ci);
753            }
754        }
755    }
756    ITERATE(TMetaVector, mi, domain->metas) {
757        newDomain->metas.push_back(*mi);
758    }
759    PDomain wdomain = newDomain;
760    domain = wdomain;
761    for(TExample **ri = examples; ri != _Last; ri++) {
762        (**ri).domain = wdomain;
763        if (classPos != attrs) {
764            TValue t = (**ri).values[attrs];
765            (**ri).values[attrs] = (**ri).values[classPos];
766            (**ri).values[classPos] = t;
767        }
768        (**ri).values_end += end_off;
769    }
770}
771
772void TExampleTable::addMetaAttribute(const int &id, const TValue &value)
773{ 
774  PEITERATE(ei, this)
775    (*ei).setMeta(id, value);
776
777  examplesHaveChanged();
778}
779
780
781void TExampleTable::copyMetaAttribute(const int &id, const int &source, TValue &defaultVal)
782{
783  if (source) {
784    PEITERATE(ei, this)
785      (*ei).setMeta(id, (*ei)[source]);
786    examplesHaveChanged();
787  }
788  else
789    addMetaAttribute(id, defaultVal);
790}
791
792
793void TExampleTable::removeMetaAttribute(const int &id)
794{
795  PEITERATE(ei, this)
796    (*ei).removeMetaIfExists(id);
797
798  examplesHaveChanged();
799}
800
801
802class TCompVar {
803public:
804  int varNum;
805
806  TCompVar(int vn) : varNum(vn) {}
807  bool operator()(const TExample *e1, const TExample *e2) const { return (*e1)[varNum].compare((*e2)[varNum])<0; }
808};
809
810
811void TExampleTable::sort()
812{
813  vector<int> empty;
814  sort(empty);
815}
816
817
818// Sort order is reversed (least important first!)
819void TExampleTable::sort(vector<int> &sortOrder)
820{ 
821  if (!sortOrder.size()) 
822    for(int i = domain->variables->size(); i; )
823      sortOrder.push_back(--i);
824
825  int ssize = _EndSpace-examples;
826  int lastOfs = _Last - examples;
827  TExample **temp = (TExample **)malloc(ssize * sizeof(TExample *));
828
829  try {
830    const_ITERATE(vector<int>, bi, sortOrder) {
831      int noVal = domain->getVar(*bi)->noOfValues();
832      if (noVal>0) {
833        vector<int> valf(noVal+1, 0);
834        TExample **t;
835        int id = 0;
836
837        for(t = examples; t!= _Last; t++) {
838          const TValue &val = (**t)[*bi];
839          const int intV = val.isSpecial() ? noVal : val.intV;
840          if (intV > noVal) {
841            free(temp);
842            raiseError("value out attribute '%s' of range", domain->variables->operator[](*bi)->get_name().c_str());
843          }
844          valf[intV]++;
845        }
846
847        for(vector<int>::iterator ni = valf.begin(); ni!=valf.end(); ni++) {
848          const int ini = *ni;
849          *ni = id;
850          id += ini;
851        }
852
853        for(t = examples; t!= _Last; t++) {
854          const TValue &val = (**t)[*bi];
855          const int intV = val.isSpecial() ? noVal : val.intV;
856          temp[valf[intV]++] = *t;
857        }
858
859        t = examples;
860        examples = temp;
861        temp = t;
862        _Last = examples + lastOfs;
863        _EndSpace = examples + ssize;
864      }
865
866      else
867        stable_sort(examples, _Last, TCompVar(*bi));
868    }
869  }
870  catch (...) {
871    examplesHaveChanged();
872    free(temp);
873    throw;
874  }
875
876  free(temp);
877
878  examplesHaveChanged();
879}
880
881void TExampleTable::shuffle()
882{
883  if (size() <= 1)
884    return;
885
886  if (!randomGenerator)
887    randomGenerator = mlnew TRandomGenerator();
888   
889  for(TExample **ei = examples+1; ei != _Last; ei++) {
890    const int st = randomGenerator->randint(ei - examples);
891    TExample *s = *ei;
892    *ei = examples[st];
893    examples[st] = s;
894  }
895}
896
897int TExampleTable::checkSum(const bool includeMetas)
898{ unsigned int crc;
899  INIT_CRC(crc);
900
901  for(TExample **ei = examples, **ee = _Last; ei!=ee; (*ei++)->addToCRC(crc, includeMetas));
902
903  FINISH_CRC(crc);
904  return int(crc & 0x7fffffff);
905}
906
907int TExampleTable::checkSum(const bool includeMetas) const
908{ unsigned int crc;
909  INIT_CRC(crc);
910
911  for(TExample **ei = examples, **ee = _Last; ei!=ee; (*ei++)->addToCRC(crc, includeMetas));
912
913  FINISH_CRC(crc);
914  return int(crc & 0x7fffffff);
915}
916
917bool TExampleTable::hasMissing() const
918{
919  for(TExample **ei = examples, **ee = _Last; ei != ee; ei++)
920    if ((*ei)->hasMissing())
921      return true;
922  return false;
923}
924
925
926bool TExampleTable::hasMissingClass() const
927{
928  if (!domain->classVar)
929    raiseError("data has no class");
930   
931  for(TExample **ei = examples, **ee = _Last; ei != ee; ei++)
932    if ((*ei)->missingClass())
933      return true;
934  return false;
935}
936
937void TExampleTable::sortByPointers()
938{
939  std::sort((int *)examples, (int *)_Last);
940}
Note: See TracBrowser for help on using the repository browser.