source: orange/source/orange/table.cpp @ 10596:54f9c123f145

Revision 10596:54f9c123f145, 21.3 KB checked in by Matija Polajnar <matija.polajnar@…>, 2 years ago (diff)

Urgent bugfix: Refactor CRC variables from unsigned long to unsigned int to make it work properly on 64-bit machines (with 64-bit Python and libraries). Fixes #1146.

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