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

Revision 10596:54f9c123f145, 11.2 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.

RevLine 
[34]1/*
2    This file is part of Orange.
[6531]3   
4    Copyright 1996-2010 Faculty of Computer and Information Science, University of Ljubljana
5    Contact: janez.demsar@fri.uni-lj.si
[34]6
[6531]7    Orange is free software: you can redistribute it and/or modify
[34]8    it under the terms of the GNU General Public License as published by
[6531]9    the Free Software Foundation, either version 3 of the License, or
[34]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
[6531]18    along with Orange.  If not, see <http://www.gnu.org/licenses/>.
[34]19*/
20
21
22#include <algorithm>
23#include <iomanip>
24#include "stladdon.hpp"
25#include "vars.hpp"
26#include "domain.hpp"
27
28#include "examplegen.hpp"
29#include "values.hpp"
30#include "distvars.hpp"
31
32#include "examples.ppp"
[272]33#include "crc.h"
[34]34
[1337]35DEFINE_TOrangeVector_classDescription(PExample, "TExampleList", true, ORANGE_API)
[580]36
[4928]37long exampleId = 0;
38
[4937]39long getExampleId()
40{ return ++exampleId; }
41 
[34]42TExample::TExample()
43: values(NULL),
[823]44  values_end(NULL),
[9401]45  classes_end(NULL),
[4928]46  name(NULL),
47  id(getExampleId())
[34]48{}
49
50
[316]51TExample::TExample(PDomain dom, bool initMetas)
[34]52: domain(dom),
53  values(NULL),
[823]54  values_end(NULL),
[9401]55  classes_end(NULL),
[4928]56  name(NULL),
57  id(getExampleId())
[34]58{ if (!dom)
59    raiseError("example needs domain");
60
61  const int attrs = domain->variables->size();
[9410]62  const int classes = domain->classVars->size();
[9401]63  TValue *vi = values = mlnew TValue[attrs+classes];
[34]64  values_end = values + attrs;
[9401]65  classes_end = values_end + classes;
[34]66  PITERATE(TVarList, di, dom->variables)
67    *(vi++) = (*di)->DK();
[9410]68  PITERATE(TVarList, ci, dom->classVars) {
69    *(vi++) = (*ci)->DK();
[9401]70  }
[316]71  if (initMetas)
72    ITERATE(TMetaVector, mi, dom->metas)
[2751]73      if (!(*mi).optional)
74        setMeta((*mi).id, (*mi).variable->DK());
[34]75}
76
77
[316]78TExample::TExample(const TExample &orig, bool copyMetas)
[34]79: domain(orig.domain),
[823]80  meta(copyMetas ? orig.meta : TMetaValues()),
[4928]81  name(orig.name ? new string(*orig.name) : NULL),
82  id(orig.id)
[34]83{ if (domain) {
84    const int attrs = domain->variables->size();
[9401]85    const int classes = orig.classes_end - orig.values_end;
86    TValue *vi = values = mlnew TValue[attrs+classes];
[34]87    values_end = values + attrs;
[9401]88    classes_end = values_end + classes;
89    for(TValue *origi = orig.values, *thisi = values; thisi != classes_end; *(thisi++) = *(origi++));
[34]90  }
[9401]91  else 
92      values = values_end = classes_end = NULL;
[34]93}
94
95
[316]96TExample::TExample(PDomain dom, const TExample &orig, bool copyMetas)
[34]97: domain(dom),
[834]98  meta(),
[4928]99  name(NULL),
100  id(orig.id)
[34]101{ if (!dom)
[580]102    raiseError("example needs a domain");
[34]103
104  const int attrs = domain->variables->size();
[9410]105  const int classes = domain->classVars->size();
[9401]106  values = mlnew TValue[attrs + classes];
[34]107  values_end = values + attrs;
[9401]108  classes_end = values_end + classes;
[834]109  domain->convert(*this, orig, !copyMetas);
[34]110}
111
112
[1337]113void TExample::insertVal(TValue &srcval, PVariable var, const long &metaID, vector<bool> &defined)
[580]114{
[603]115  int position = var ? domain->getVarNum(var, false) : ILLEGAL_INT;
[580]116
[603]117  if (position != ILLEGAL_INT) {
118    // Check if this is an ordinary attribute
119    if (position >= 0) {
[1337]120      if (!mergeTwoValues(values[position], srcval, defined[position]))
[7665]121        raiseError("ambiguous value of attribute '%s'", var->get_name().c_str());
[1337]122      else
123        defined[position] = true;
[603]124    }
125   
126    else {
127      // Is it meta?
128      if (hasMeta(position)) {
[1337]129        if (!mergeTwoValues(meta[metaID], srcval, true))
[7665]130          raiseError("ambiguous value for meta-attribute '%s'", var->get_name().c_str());
[603]131      }
132      else
133        setMeta(position, srcval);
134    }
135  }
136
137
138  else {
139    /* This attribute is not required in the example.
140       But if it is meta and there is no other meta-attribute with same id,
141       we shall copy it nevertheless */
142    if (metaID && !domain->getMetaVar(metaID, false))
143      if (hasMeta(metaID)) {
[1337]144        if (!mergeTwoValues(meta[metaID], srcval, true))
[580]145          raiseError("ambiguous value for meta-attribute %i", position);
[603]146      }
147      else
[1337]148        setMeta(metaID  , srcval);
[580]149  }
150}
151
152
153TExample::TExample(PDomain dom, PExampleList elist)
[823]154: domain(dom),
[4928]155  name(NULL),
156  id(elist->size() ? elist->front()->id : getExampleId())
[580]157{
158  if (!dom)
159    raiseError("example needs a domain");
[9410]160  if (dom->classVars->size()) {
[9401]161      raiseError("example merging does not support multiple classes");
162  }
[580]163
[603]164  const int attrs = domain->variables->size();
[9410]165  const int classes = domain->classVars->size();
[1337]166  vector<bool> defined(attrs, false);
167
[603]168  TValue *vi = values = mlnew TValue[attrs];
169  values_end = values + attrs;
170  PITERATE(TVarList, di, dom->variables)
171    *(vi++) = (*di)->DK();
172
[580]173  PITERATE(TExampleList, eli, elist) {
174    TVarList::iterator vli((*eli)->domain->variables->begin());
175    TExample::iterator ei((*eli)->begin()), ee((*eli)->end());
176    for(; ei!=ee; ei++, vli++) 
177      if (!(*ei).isSpecial())
[1337]178        insertVal(*ei, *vli, 0, defined);
[580]179
180    set<int> metasNotToCopy;
181    ITERATE(TMetaVector, mai, (*eli)->domain->metas) {
182      metasNotToCopy.insert((*mai).id);
[603]183      if ((*eli)->hasMeta((*mai).id))
[1337]184        insertVal((*eli)->getMeta((*mai).id), (*mai).variable, (*mai).id, defined);
[580]185    }
186
187    set<int>::iterator mend(metasNotToCopy.end());
188    ITERATE(TMetaValues, mi, (*eli)->meta)
189      if (metasNotToCopy.find((*mi).first)==mend)
[1337]190        insertVal((*mi).second, PVariable(), (*mi).first, defined);
[603]191  }
192
193  ITERATE(TMetaVector, mai, domain->metas)
[2751]194    if (!(*mai).optional && !hasMeta((*mai).id))
[603]195      setMeta((*mai).id, (*mai).variable->DK());
[580]196}
197
198
[34]199TExample::~TExample()
[823]200{ 
201  mldelete[] values; 
202  if (name)
203    delete name;
204}
[34]205
206
[70]207int TExample::traverse(visitproc visit, void *arg) const
208{ TRAVERSE(TOrange::traverse);
209 
[9401]210  for(TValue *vi = values, *ve = classes_end; vi!=ve; vi++)
[70]211    if (vi->svalV)
212      PVISIT(vi->svalV);
213
214  const_ITERATE(TMetaValues, mi, meta)
215    if ((*mi).second.svalV)
216      PVISIT((*mi).second.svalV);
217
218  return 0;
219}
220
221
222int TExample::dropReferences()
223{
[9401]224  for(TValue *vi = values, *ve = classes_end; vi!=ve; vi++)
[70]225    if (vi->svalV)
226      vi->svalV.~PSomeValue();
227
228  const_ITERATE(TMetaValues, mi, meta)
229    if ((*mi).second.svalV)
230      (*mi).second.svalV.~PSomeValue();
231
[823]232  delete name;
233  name = NULL;
234
[70]235  return 0;
236}
237
238
[34]239TExample &TExample::operator =(const TExample &orig)
[284]240{
241  if (!orig.domain) {
[9401]242    if (values)
243       mldelete[] values;
244    values = values_end = classes_end = NULL;
[284]245    domain = PDomain();
246  }
[34]247
[284]248  else {
[9401]249    const int attrs = orig.values_end - orig.values;
250    const int classes = orig.classes_end - orig.values_end;
[284]251    if (domain != orig.domain) {
[9401]252      if ((values_end - values != attrs) || (classes_end - values_end != classes)) {
[284]253        if (values)
254          mldelete[] values;
[9401]255        values = mlnew TValue[attrs+classes];
[284]256        values_end = values + attrs;
[9401]257        classes_end = values_end + classes;
[284]258      }
259      domain = orig.domain;
260    }
261
[9401]262    for(TValue *origi = orig.values, *thisi = values; thisi != classes_end; *(thisi++) = *(origi++));
[34]263  }
264
265  meta = orig.meta;
[823]266 
267  if (name) {
268    delete name;
269    name = NULL;
270  }
271  if (orig.name)
272    name = new string(*orig.name);
273
[4928]274  id = orig.id;
275 
[34]276  return *this;
277}
278
279
[1580]280TValue TExample::getValue(PVariable &var) const
281{
282  // if there is no getValueFrom, throw an exception
283  const int position = domain->getVarNum(var, var->getValueFrom);
284  return position != ILLEGAL_INT ? operator[](position) : var->computeValue(*this);
285}
286
[34]287TValue &TExample::operator[] (PVariable &var)
[131]288{ return operator[](domain->getVarNum(var)); }
[34]289
290
291const TValue &TExample::operator[] (PVariable &var) const
[131]292{ return operator[](domain->getVarNum(var)); }
[34]293
294
295TValue &TExample::operator[] (const string &name)
[131]296{ return operator[](domain->getVarNum(name)); }
[34]297
298
299const TValue &TExample::operator[] (const string &name) const
[131]300{ return operator[](domain->getVarNum(name)); }
[34]301
302
[2788]303const TValue &TExample::missingMeta(const int &i) const
304{
305  const TMetaDescriptor *md = domain->metas[i];
306  if (md)
307    if (md->optional)
308      return md->variable->DK();
309    else
[7665]310      if (md->variable->get_name().size())
311        raiseError("the value of meta attribute '%s' is missing", md->variable->get_name().c_str());
[2788]312
313  // no descriptor or no name
314  raiseError("meta value with id %i is missing", i);
315  throw 0;
316}
317
318
[34]319bool TExample::operator < (const TExample &other) const
320{ 
321  if (domain != other.domain)
322    raiseError("examples are from different domains");
323  return compare(other)<0;
324}
325
326
327bool TExample::operator == (const TExample &other) const
328{ 
329  if (domain != other.domain)
330    raiseError("examples are from different domains");
331
[9410]332  int Na = domain->variables->size() + domain->classVars->size();
[34]333  if (!Na)
334    return true;
335  for (const_iterator vi1(begin()), vi2(other.begin()); (*vi1==*vi2) && --Na; vi1++, vi2++);
336  return !Na;
337}
338
339
[2501]340int TExample::compare(const TExample &other, const bool ignoreClass) const
[34]341{ if (domain != other.domain)
342    raiseError("examples are from different domains");
343
[9401]344  int Na = domain->variables->size();
345  if (ignoreClass) {
346      if (domain->classVar) {
347          Na--;
348      }
349  }
350  else {
[9410]351      Na += domain->classVars->size();
[9401]352  }
[34]353  if (!Na)
354    return true;
355
[9401]356  const_iterator i1(begin()), i2(other.begin());
[34]357  int comp;
358  while (0==(comp= (*(i1++)).compare(*(i2++))) && --Na);
359  return comp;
360}
361
362
[2501]363bool TExample::compatible(const TExample &other, const bool ignoreClass) const
[34]364{ if (domain != other.domain)
365    raiseError("examples are from different domains");
366 
[9401]367  int Na = domain->variables->size();
368  if (ignoreClass) {
369      if (domain->classVar) {
370          Na--;
371      }
372  }
373  else {
[9410]374      Na += domain->classVars->size();
[9401]375  }
[34]376  if (!Na)
377    return true;
378  for (const_iterator i1(begin()), i2(other.begin()); (*i1).compatible(*i2) && --Na; i1++, i2++);
379  return !Na;
380}
381
[59]382
[4238]383#include "stringvars.hpp"
384
[10596]385inline void addToCRC(unsigned int &crc, const PVarList &vars, TValue *&vli)
[1262]386{
[9401]387  const_PITERATE(TVarList, vi, vars) {
[59]388    if ((*vi)->varType == TValue::INTVAR)
[10591]389      add_CRC(vli->isSpecial() ? ILLEGAL_INT : vli->intV, crc);
[4238]390    else if (((*vi)->varType == TValue::FLOATVAR))
391      add_CRC(vli->isSpecial() ? ILLEGAL_FLOAT : vli->floatV, crc);
392    else if ((*vi)->varType == STRINGVAR) {
393      if (vli->isSpecial() || !vli->svalV)
[10591]394        add_CRC(ILLEGAL_INT, crc);
[4238]395      else
396        add_CRC(vli->svalV.AS(TStringValue)->value.c_str(), crc);
397    }
[273]398    vli++;
399  }
[9401]400}
401
[10596]402void TExample::addToCRC(unsigned int &crc, const bool includeMetas) const
[9401]403{
404  TValue *vli = values;
405  ::addToCRC(crc, domain->variables, vli);
[9410]406  ::addToCRC(crc, domain->classVars, vli);
[4238]407 
408  if (includeMetas) {
409    const_ITERATE(TMetaValues, mi, meta) {
410      add_CRC((const unsigned long)(mi->first), crc);
411      const TValue &val = mi->second;
412      if (val.varType == TValue::INTVAR)
[10591]413        add_CRC(val.isSpecial() ? ILLEGAL_INT : val.intV, crc);
[4238]414      else if (val.varType == TValue::INTVAR)
415        add_CRC(val.isSpecial() ? ILLEGAL_FLOAT: val.floatV, crc);
416      else if (val.varType == STRINGVAR) {
417        if (val.isSpecial()  || !vli->svalV)
[10591]418          add_CRC(ILLEGAL_INT, crc);
[4238]419        else
420          add_CRC(val.svalV.AS(TStringValue)->value.c_str(), crc);
421      }
422    }
423  }
[1262]424}
[272]425
[1262]426
[4238]427int TExample::sumValues(const bool includeMetas) const
[10596]428{ unsigned int crc;
[1262]429  INIT_CRC(crc);
[4238]430  addToCRC(crc, includeMetas);
[272]431  FINISH_CRC(crc);
[281]432  return int(crc & 0x7fffffff);
[59]433}
Note: See TracBrowser for help on using the repository browser.