source: orange/source/orange/table.cpp @ 11727:78a05eef3f20

Revision 11727:78a05eef3f20, 21.1 KB checked in by Ales Erjavec <ales.erjavec@…>, 6 months ago (diff)

Fixed a bug in Table iteration after deleting all elements.

(fixes #1333)

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