source: orange/source/orange/cls_value.cpp @ 11703:9b8d8ab7820c

Revision 11703:9b8d8ab7820c, 36.6 KB checked in by janezd <janez.demsar@…>, 7 months ago (diff)

Removed the GPL copyright notice from all files except orangeqt.

RevLine 
[8265]1#ifdef _MSC_VER
2 #pragma warning (disable : 4786 4114 4018 4267 4244)
3#endif
4
5#include "cls_value.hpp"
6#include "cls_orange.hpp"
7#include "vars.hpp"
8#include "stringvars.hpp"
9#include "pythonvars.hpp"
10#include "values.hpp"
11
12#include "vectortemplates.hpp"
13
14#include "externs.px"
15
16
17#define CHECK_VARIABLE \
18  if (!self->variable) PYERROR(PyExc_TypeError, "'variable' not set", PYNULL);
19
20#define CHECK_SPECIAL_OTHER \
21  if (self->value.isSpecial()) \
22    PYERROR(PyExc_TypeError, "attribute value unknown", PYNULL); \
23  if ((self->value.varType!=TValue::INTVAR) && (self->value.varType!=TValue::FLOATVAR)) \
24    PYERROR(PyExc_TypeError, "attribute is not an ordinary discrete or continuous", PYNULL);
25
26
27
28DATASTRUCTURE(Value - Orange.data.Value, TPyValue, 0)
29ABSTRACT(SomeValue - Orange.core.SomeValue, Orange)
30
31/* Converts a value into an appropriate python variable.
32   Behaves as convertToPythonNative(const TValue &, PVariable)
33   when the variable is not given. */
34
35PyObject *convertToPythonNative(const TValue &val)
36{ return convertToPythonNative(val, PVariable()); }
37
38
39
40/* Converts a value into an appropriate python variable.
41   Behaves as convertToPythonNative(const TValue &, PVariable);
42   variable can be there or not. */
43
44PyObject *convertToPythonNative(const TPyValue *value)
45{ return convertToPythonNative(value->value, value->variable); }
46
47
48
49/* Converts a value into an appropriate python variable.
50   If value is known (e.g. not DC, DK...)
51    - continuous values are returned as ordinary python floats
52    - discrete are returned as strings (variable is required)
53    - string values are returned as strings
54    - other values are return as ordinary orange objects
55   If value is special
56    - if the variable is given, its val2str is used to get a string
57    - if the variable is not given, '?', '~' and '.' are returned
58      for DK, DC and other, respectively.
59
60   FAILS if the value is discrete and variable is not given
61*/
62
63PyObject *convertToPythonNative(const TValue &val, PVariable var)
64{
65  if ((val.varType==TValue::FLOATVAR) && !val.isSpecial())
66    return PyFloat_FromDouble(double(val.floatV));
67
68  if (val.varType == PYTHONVAR) {
69    PyObject *res = val.svalV ? ((TPythonValue &)(val.svalV.getReference())).value : Py_None;
70    Py_INCREF(res);
71    return res;
72  }
73
74  if ((val.varType == STRINGVAR) && val.svalV) {
75    string s;
76    val.svalV.AS(TStringValue)->val2str(s);
77    return PyString_FromString(s.c_str());
78  }
79
80  if ((val.varType!=TValue::INTVAR) && val.svalV)
81    return WrapOrange((const_cast<TValue &>(val)).svalV);
82
83  if (var) { // && (val.varType == TValue::INTVAR || val.isSpecial)
84    string vs;
85    var->val2str(val, vs);
86    return PyString_FromString(vs.c_str());
87  }
88
89  if (val.isSpecial())
90    if (val.isDK())
91      return PyString_FromString("?");
92    else if (val.isDC()) 
93      return PyString_FromString("~");
94    else
95      return PyString_FromString(".");
96
97  PYERROR(PyExc_TypeError, "unknown value type", PYNULL);
98}
99
100
101/* The main routine for converting values from python to TValue.
102   If arguments are given as a
103   - Value, it is simply copied.
104       The variable is checked if given.
105   - SomeValue, it is copied as such.
106       If the variable is discrete or continuous, SomeValue must
107       be DiscDistribution or ContDistribution.
108   - string, we convert it to a value
109       The variable must be given unless the string is '?', '~'
110       (in this case INTVAR is ocnstructed)
111       We could return a StringValue here, but if user passes a
112       string without descriptor it is more probable that he just
113       forgot it. I doubt that many would construct StringValues.)
114   - int - if variable is given and is discrete, an integer value
115           is constructed. If the variable is derived from
116           EnumVariable the range is also tested
117         - if variable is given and is continuous, a continuous
118           value is constructed
119         - if variable is given and is of other type, an error is
120           raised
121         - if the variable is not given, an integer value is constructed
122   - float - a continuous value is constructed.
123       If the variable is given, it is checked that it is continuous
124   - other types: if it can be converted to float and the variable is
125       given and is continuous, a continuous value is constructed.
126       Otherwise, an exception is raised.         
127*/
128
129bool convertFromPython(PyObject *args, TValue &value, PVariable var)
130{
131  if (PyOrValue_Check(args)) {
132    if (var && PyValue_AS_Variable(args) && (PyValue_AS_Variable(args)!=var)) {
133      PyErr_Format(PyExc_TypeError, "wrong attribute value (expected value of '%s', got value of '%s')", var->get_name().c_str(), PyValue_AS_Variable(args)->get_name().c_str());
134      return false;
135    }
136    else
137      value = PyValue_AS_Value(args);
138    return true;
139  }
140
141  if (PyOrSomeValue_Check(args)) {
142    if (var) {
143      if ((var->varType==TValue::INTVAR) && !PyOrDiscDistribution_Check(args)) {
144        PyErr_Format(PyExc_TypeError, "attribute '%s' expects DiscDistribution, '%s' given", var->get_name().c_str(), args->ob_type->tp_name);
145        return false;
146      }
147      if ((var->varType==TValue::FLOATVAR) && !PyOrContDistribution_Check(args)) {
148        PyErr_Format(PyExc_TypeError, "attribute '%s' expects ContDistribution, '%s' given", var->get_name().c_str(), args->ob_type->tp_name);
149        return false;
150      }
151    }
152    int vtype;
153    if (PyOrDiscDistribution_Check(args))
154      vtype = TValue::INTVAR;
155    else if (PyOrContDistribution_Check(args))
156      vtype = TValue::FLOATVAR;
157    else if (PyOrStringValue_Check(args))
158      vtype = STRINGVAR;
159    else if (PyOrPythonValue_Check(args))
160      vtype = PYTHONVAR;
161    else
162      raiseError("unknovn variable type");
163
164    value = TValue(PyOrange_AsSomeValue(args), vtype);
165    return true;
166  }
167 
168  if (PyString_Check(args)) {
169    char *str = PyString_AsString(args);
170    if (var)
171      var->str2val(str, value);
172    else
173      if (!strcmp(str, "?"))
174        value = TValue(TValue::INTVAR, valueDK);
175      else if (!strcmp(str, "~"))
176        value = TValue(TValue::INTVAR, valueDC);
177      else {
178        PyErr_Format(PyExc_TypeError, "cannot convert '%s' to a value of an unknown attribute", str);
179        return false;
180      }
181    return true;
182  }
183 
184  if (var && var->varType == PYTHONVAR) {
185    value = TValue(mlnew TPythonValue(args), PYTHONVAR);
186    return true;
187  }
188 
189  if (args == Py_None) {
190    value = var ? var->DK() : TValue(TValue::INTVAR, valueDK);
191    return true;
192  }
193
194  if (PyInt_Check(args)) {
195    int ii = int(PyInt_AsLong(args));
196
197    if (var) {
198      if (var->varType == TValue::FLOATVAR) {
199        value = TValue(float(ii));
200        return true;
201      }
202
203      if (var->varType == TValue::INTVAR) {
204        if (var.is_derived_from(TEnumVariable)) {
205          int nv = var.AS(TEnumVariable)->noOfValues();
206          if (ii >= nv) {
207            PyErr_Format(PyExc_TypeError, "value index %i out of range (0 - %i)", ii, nv-1);
208            return false;
209          }
210        }
211
212        value = TValue(ii);
213        return true;
214      }
215
216      PyErr_Format(PyExc_TypeError,  "cannot convert an integer to a value of attribute '%s'", var->get_name().c_str());
217      return false;
218    }
219
220    value = TValue(ii);
221    return true;
222  }
223
224  if (PyFloat_Check(args)) {
225    if (var && (var->varType != TValue::FLOATVAR)) {
226      PyErr_Format(PyExc_TypeError,  "cannot convert a float to a value of attribute '%s'", var->get_name().c_str());
227      return false;
228    }
229
230    value = TValue(float(PyFloat_AsDouble(args)));
231    return true;
232  }
233
234  if (var && (var->varType == TValue::FLOATVAR)) {
235    PyObject *pyfloat = PyNumber_Float(args);
236    if (!pyfloat) {
237      PyErr_Format(PyExc_TypeError, "cannot convert an object of type '%s' to value of attribute '%s'", args->ob_type->tp_name, var->get_name().c_str());
238      return false;
239    }
240
241    value = TValue(float(PyFloat_AsDouble(pyfloat)));
242    Py_DECREF(pyfloat);
243    return true;
244  }
245
246  if (var)
247    PyErr_Format(PyExc_TypeError,  "cannot convert an object of type '%s' to value of attribute '%s'", args->ob_type->tp_name, var->get_name().c_str());
248  else
249    PyErr_Format(PyExc_TypeError,  "cannot convert an object of type '%s' to value of attribute", args->ob_type->tp_name);
250
251  return false;
252}
253
254
255/* Builds a TPyValue from arguments given in Python.
256   See Value_FromArguments for details. */
257
258bool convertFromPython(PyObject *args, TPyValue *&value)
259{
260  value = (TPyValue *)Value_FromArguments((PyTypeObject *)&PyOrValue_Type, args);
261  return value!=NULL;
262}
263
264
265
266/* The main constructor for TPyValue.
267   Gets a value and descriptor, allocates the memory and assigns fields. */
268
269PyObject *Value_FromVariableValueType(PyTypeObject *type, PVariable var, const TValue &val)
270{ 
271  TPyValue *value = PyObject_GC_New(TPyValue, type);
272  if (!value)
273    return PYNULL;
274
275  /* The below is needed since 'value' was allocated in C code, so it's
276     constructor has never been called and the below fields (wrapped pointers)
277     contain random data, which would lead to crash when trying to deallocate
278     them. */
279  value->value.svalV.init();
280  value->variable.init();
281
282  value->value = val;
283  value->variable = var;
284
285  PyObject_GC_Track(value);
286
287  return (PyObject *)value;
288}
289
290
291
292/* Constructs a value from arguments in Python. Arguments must be given as a tuple
293   with at least one element.
294   - If the single element is a variable, a DK() value for that attribute is returned
295   - Otherwise, it is converted using convertFromPython, without descriptor given
296
297   If there are two elements
298   - If one is variable, convertFromPython is used, passing the variable and the other
299   - Otherwise, both must be integers and are used for varType and valueType.
300*/
301
302PyObject *Value_FromArguments(PyTypeObject *type, PyObject *args)
303{   
304  PyTRY
305    PyObject *obj1;
306    PyObject *obj2 = NULL;
307
308    if (!PyArg_ParseTuple(args, "O|O:Value", &obj1, &obj2))
309      return PYNULL;
310
311    if (!obj2) {
312      if (PyOrVariable_Check(obj1))
313        return Value_FromVariableType(type, PyOrange_AsVariable(obj1));
314      else {
315        TValue val;
316        return convertFromPython(obj1, val) ? Value_FromValueType(type, val) : PYNULL;
317      }
318    }
319
320    TValue val;
321    if (PyOrVariable_Check(obj1)) {
322      const PVariable &var = PyOrange_AsVariable(obj1);
323      return convertFromPython(obj2, val, var) ? Value_FromVariableValueType(type, var, val) : PYNULL;
324    }
325    else if (PyOrVariable_Check(obj2)) {
326      const PVariable &var = PyOrange_AsVariable(obj2);
327      return convertFromPython(obj1, val, var) ? Value_FromVariableValueType(type, var, val) : PYNULL;
328    }
329    else if (PyInt_Check(obj1) && PyInt_Check(obj2)) {
330      int vartype = int(PyInt_AsLong(obj1));
331
332      if (vartype == STRINGVAR)
333        return Value_FromValueType(type, TValue(STRINGVAR, (signed char)PyInt_AsLong(obj2)));
334
335      if (vartype > TValue::FLOATVAR) {
336        PyErr_Format(PyExc_IndexError, "invalid value type (%i)", vartype);
337        return PYNULL;
338      }
339       
340      return Value_FromValueType(type, TValue((char)vartype, (signed char)PyInt_AsLong(obj2)));
341    }
342
343    PYERROR(PyExc_TypeError, "Value(): invalid arguments", PYNULL);
344  PyCATCH
345}
346
347
348
349
350PyObject *Value_new(PyTypeObject *type, PyObject *args, PyObject *keywords)  BASED_ON(ROOT, "([Variable], [int | float | Value | ...])")
351{ return Value_FromArguments(type, args); }
352
353
354void Value_dealloc(TPyValue *self)
355{ self->variable = PVariable();
356  self->value.~TValue();
357
358  if (PyObject_IsPointer(self)) {
359    PyObject_GC_UnTrack((PyObject *)self);
360    self->ob_type->tp_free((PyObject *)self); 
361  }
362}
363
364
365int Value_traverse(TPyValue *self, visitproc visit, void *arg)
366{ PVISIT(self->variable);
367  PVISIT(self->value.svalV);
368  return 0;
369}
370
371
372void Value_clear(TPyValue *self)
373{ self->variable=PVariable();
374  self->value.~TValue();
375}
376
377
378/* Returns a string representations for a value.
379   - If descriptor is given, its val2str should take care of everything
380   - If the value is special, we know that to do
381   - If value is
382     - FLOATVAR, convert a floatV
383     - INTVAR, print a intV in brackets
384     - else if svalV is given, it should take care of itself
385     - else, we return "###"
386*/
387
388char *pvs = NULL;
389const char *TPyValue2string(TPyValue *self)
390{ if (self->variable) {
391    string str;
392    self->variable->val2str(self->value, str);
393    pvs = (char *)realloc(pvs, str.size()+1);
394    strcpy(pvs, str.c_str());
395  }
396  else {
397    if (self->value.isDK())
398      return "?";
399    if (self->value.isDC())
400      return "~";
401    if (self->value.isSpecial())
402      return ".";
403
404    pvs = (char *)realloc(pvs, 16);
405    if (self->value.varType==TValue::FLOATVAR)
406      sprintf(pvs, "%f", self->value.floatV);
407    else if (self->value.varType==TValue::INTVAR)
408      sprintf(pvs, "<%i>", self->value.intV);
409    else if (self->value.svalV) {
410      string str;
411      self->value.svalV->val2str(str);
412      pvs = (char *)realloc(pvs, str.size()+1);
413      strcpy(pvs, str.c_str());
414    }
415    else
416      return "###";
417  }
418
419  return pvs;
420}
421
422
423
424/* Compares two values. The first is always TPyValue.
425   Comparisons of discrete are based on intV not on string representations
426   If both are TPyValue, the values must be of same type
427     - If both are special, they are equal/different if the valueType is
428       equal/different. Operators >, <, <= and >= are not defined.
429     - If only one is special, it's an error
430     - If they are discrete and descriptors are known but different,
431       each value's string representation is compared to the other's,
432       both comparisons are made and must give the same result.
433       If not, it's an error.
434     - Otherwise, intV's r floatV's are compared
435   If the other is an integer, it can be compared with discrete and
436     continuous attributes
437   If the other is a float, it can be compared with continuous attrs.
438   If the first value is special and the other is string "~" or "?",
439     they are compared as described above.
440   Otherwise, the descriptor for the first value must be known and is
441     used to convert the second value (if possible). The values are
442     then compared by the same rules as if both were PyValues
443     (except that both obviously have the same descriptor).
444*/
445
446#define errUndefinedIf(cond) if (cond) PYERROR(PyExc_TypeError, "Value.compare: cannot compare with undefined values", PYNULL);
447
448PyObject *richcmp_from_sign(const int &i, const int &op)
449{ int cmp;
450  switch (op) {
451        case Py_LT: cmp = (i<0); break;
452        case Py_LE: cmp = (i<=0); break;
453        case Py_EQ: cmp = (i==0); break;
454        case Py_NE: cmp = (i!=0); break;
455        case Py_GT: cmp = (i>0); break;
456        case Py_GE: cmp = (i>=0); break;
457    default:
458      Py_INCREF(Py_NotImplemented);
459      return Py_NotImplemented;
460  }
461 
462  PyObject *res;
463  if (cmp)
464    res = Py_True;
465  else
466    res = Py_False;
467  Py_INCREF(res);
468  return res;
469}
470
471
472PyObject *Value_richcmp(TPyValue *i, PyObject *j, int op)
473{ 
474  PyTRY
475
476    const TValue &val1 = i->value;
477
478    if (PyOrValue_Check(j)) {
479      const TValue &val2 = PyValue_AS_Value(j);
480
481      if (val1.varType != val2.varType)
482        PYERROR(PyExc_TypeError, "Value.compare: can't compare values of different types", PYNULL)
483
484      if (val1.isSpecial() || val2.isSpecial())
485        if ((op==Py_EQ) || (op==Py_NE)) {
486          PyObject *res = (val1.valueType==val2.valueType) == (op==Py_EQ) ? Py_True : Py_False;
487          Py_INCREF(res);
488          return res;
489        }
490        else {
491          Py_INCREF(Py_NotImplemented);
492          return Py_NotImplemented;
493        }
494
495      // Nominal values of different attributes are treated separately
496      PVariable &var1 = i->variable;
497      PVariable &var2 = PyValue_AS_Variable(j);
498      if ((val1.varType==TValue::INTVAR) && var1 && var2 && (var1 != var2)) {
499        TValue tempval;
500        string tempstr;
501
502        var2->val2str(val2, tempstr);
503        if (var1->str2val_try(tempstr, tempval)) {
504          int cmp1 = val1.compare(tempval);
505
506          var1->val2str(val1, tempstr);
507          if (var2->str2val_try(tempstr, tempval)) {
508            int cmp2 = tempval.compare(val2);
509            bool err = true;
510            switch (op) {
511              case Py_LE:
512              case Py_GE: err = ((cmp1*cmp2) == -1); break;
513              case Py_LT:
514              case Py_GT: err = (cmp1!=cmp2); break;
515              case Py_EQ:
516              case Py_NE: err = ((cmp1==0) != (cmp2==0)); break;
517            }
518
519            if (err)
520              PYERROR(PyExc_TypeError, "Value.compare: values are of different types and have different orders", PYNULL);
521          }
522
523          return richcmp_from_sign(cmp1, op);
524        }
525
526        var1->val2str(val1, tempstr);
527        if (var2->str2val_try(tempstr, tempval))
528          return richcmp_from_sign(tempval.compare(val2), op);
529
530        PYERROR(PyExc_TypeError, "Value.compare: values are of different types and cannot be compared", PYNULL);
531      }
532
533      // Not nominal OR both values or of the same attribute
534      return richcmp_from_sign(val1.compare(val2), op);
535    }
536
537
538    if (PyInt_Check(j)) {
539      errUndefinedIf(val1.isSpecial());
540
541      if (val1.varType==TValue::INTVAR)
542        return richcmp_from_sign(val1.intV - (int)PyInt_AsLong(j), op);
543      else if (val1.varType==TValue::FLOATVAR)
544        return richcmp_from_sign(sign(val1.floatV - (int)PyInt_AsLong(j)), op);
545    }
546
547    else if (PyFloat_Check(j)) {
548      errUndefinedIf(val1.isSpecial());
549      if (val1.varType==TValue::FLOATVAR)
550        return richcmp_from_sign(sign(val1.floatV - (float)PyFloat_AsDouble(j)), op);
551    }
552
553    else if (PyString_Check(j) && val1.isSpecial() && ((op==Py_EQ) || (op==Py_NE))) {
554      char *s = PyString_AsString(j);
555      PyObject *res = NULL;
556      if (!strcmp(s, "~"))
557        res = (val1.valueType==valueDC) == (op==Py_EQ) ? Py_True : Py_False;
558      else if (!strcmp(s, "?"))
559        res = (val1.valueType==valueDK) == (op==Py_EQ) ? Py_True : Py_False;
560      if (res) {
561        Py_INCREF(res);
562        return res;
563      }
564    }
565
566    if (i->variable) {
567      TValue val2;
568      if (!convertFromPython(j, val2, i->variable))
569        return PYNULL;
570
571      if (val1.isSpecial() || val2.isSpecial())
572        if ((op==Py_EQ) || (op==Py_NE)) {
573          PyObject *res = (val1.valueType==val2.valueType) == (op==Py_EQ) ? Py_True : Py_False;
574          Py_INCREF(res);
575          return res;
576        }
577        else {
578          Py_INCREF(Py_NotImplemented);
579          return Py_NotImplemented;
580        }
581
582      return richcmp_from_sign(val1.compare(val2), op);
583    }
584     
585    Py_INCREF(Py_NotImplemented);
586    return Py_NotImplemented;
587
588  PyCATCH
589}
590#undef errUndefinedIf
591
592
593
594PyObject *Value_str(TPyValue *self)
595{ PyTRY
596    return PyString_FromString(TPyValue2string(self)); 
597  PyCATCH
598}
599
600
601PyObject *Value_repr(TPyValue *self)
602{ PyTRY
603    if (self->variable)
604      return PyString_FromFormat("<orange.Value '%s'='%s'>", self->variable->get_name().c_str(), TPyValue2string(self));
605    else
606      return PyString_FromFormat("<orange.Value '%s'>", TPyValue2string(self)); 
607  PyCATCH
608}
609
610
611bool checkSpecial(TPyValue *self, char *casttype)
612{
613  if (self->value.isSpecial()) {
614    if (self->variable && self->variable->get_name().length())
615      PyErr_Format(PyExc_TypeError, "value of '%s' is unknown and cannot be %s", self->variable->get_name().c_str(), casttype);
616    else
617      PyErr_Format(PyExc_TypeError, "attribute value is unknown and cannot be %s", casttype);
618    return false;
619  }
620
621  return true;
622}
623
624PyObject *Value_int(TPyValue *self)
625{ PyTRY
626    if (!checkSpecial(self, "cast to an integer"))
627      return PYNULL;
628
629    return Py_BuildValue("i", (self->value.varType==TValue::INTVAR) ? self->value.intV : int(self->value.floatV)); 
630  PyCATCH
631}
632
633
634PyObject *Value_long(TPyValue *self)
635{ PyTRY
636    if (!checkSpecial(self, "cast to a long integer"))
637      return PYNULL;
638
639    return Py_BuildValue("l", (self->value.varType==TValue::INTVAR) ? long(self->value.intV) : long(self->value.floatV)); 
640  PyCATCH
641}
642
643
644PyObject *Value_float(TPyValue *self)
645{ PyTRY
646    if (!checkSpecial(self, "cast to a float"))
647      return PYNULL;
648
649    return Py_BuildValue("f", (self->value.varType==TValue::INTVAR) ? float(self->value.intV) : self->value.floatV); 
650  PyCATCH
651}
652
653
654inline bool checkForNumerical(const TValue &val1, const TValue &val2, const char *op)
655{
656  if (val1.isSpecial() || val2.isSpecial())
657    PYERROR(PyExc_TypeError, "cannot %s unknown values", false);
658  if ((val1.varType!=TValue::FLOATVAR) || (val2.varType!=TValue::FLOATVAR))
659    PYERROR(PyExc_TypeError, "cannot %s non-continuous values", false);
660  return true;
661}
662
663
664#define VALUEOP(opname,FUN,opverb) \
665PyObject *Value_##opname(TPyValue *self, PyObject *other) \
666{ PyTRY \
667    const TValue &val1 = self->value; \
668\
669    if (PyOrValue_Check(other)) { \
670      const TValue &val2 = PyValue_AS_Value(other); \
671      return checkForNumerical(val1, val2, opverb) ? PyFloat_FromDouble(val1.floatV FUN val2.floatV) : PYNULL; \
672    } \
673\
674    TValue val2; \
675    return convertFromPython(other, val2, self->variable) && checkForNumerical(val1, val2, opverb) ? PyFloat_FromDouble(val1.floatV FUN val2.floatV) : PYNULL; \
676  PyCATCH \
677}
678
679
680PyObject *Value_add(TPyValue *self, PyObject *other);
681PyObject *Value_sub(TPyValue *self, PyObject *other);
682PyObject *Value_mul(TPyValue *self, PyObject *other);
683PyObject *Value_div(TPyValue *self, PyObject *other);
684
685VALUEOP(add,+,"sum")
686VALUEOP(sub,-,"subtract")
687VALUEOP(mul,*,"multiply")
688VALUEOP(div,/,"divide")
689
690
691PyObject *Value_pow(TPyValue *self, PyObject *other, PyObject *)
692{ PyTRY
693    const TValue &val1 = self->value;
694   
695    if (!val1.isSpecial() && (val1.varType==TValue::FLOATVAR) && (val1.floatV<=0))
696      PYERROR(PyExc_TypeError, "negative base value", false);
697
698    if (PyOrValue_Check(other)) { 
699      const TValue &val2 = PyValue_AS_Value(other); 
700      return checkForNumerical(val1, val2, "add") ? PyFloat_FromDouble(exp(val2.floatV*log(val1.floatV))) : PYNULL;
701    }
702    else {
703      TValue val2; 
704      return    convertFromPython(other, val2, self->variable)
705             && checkForNumerical(val1, val2, "add")
706           ? PyFloat_FromDouble(exp(val2.floatV*log(val1.floatV)))
707           : PYNULL;
708    }
709  PyCATCH
710}
711
712
713PyObject *Value_neg(TPyValue *self)
714{ PyTRY
715    if (!checkSpecial(self, "negated"))
716      return PYNULL;
717
718    const TValue &val1 = self->value;
719    if (val1.varType!=TValue::FLOATVAR)
720      PYERROR(PyExc_TypeError, "cannot negate non-continuous value", false);
721    return PyFloat_FromDouble(-val1.floatV);
722  PyCATCH
723}
724
725
726PyObject *Value_abs(TPyValue *self)
727{ PyTRY
728    if (self->value.isSpecial())
729      if (self->variable && self->variable->get_name().length()) {
730        PyErr_Format(PyExc_TypeError, "cannot compute an absolute value of '%s' since its value is unknown", self->variable->get_name().c_str());
731        return PYNULL;
732      }
733      else
734        PYERROR(PyExc_TypeError, "cannot compute an absolute value of attribute since its value is unknown", PYNULL);
735
736    const TValue &val1 = self->value;
737    if (val1.varType!=TValue::FLOATVAR)
738      PYERROR(PyExc_TypeError, "cannot compute abs of non-continuous value", false);
739    return PyFloat_FromDouble(fabs(val1.floatV));
740  PyCATCH
741}
742
743
744int Value_nonzero(TPyValue *i)
745{ PyTRY
746    return !i->value.isSpecial();
747  PyCATCH_1
748}
749
750
751int Value_coerce(PyObject **i, PyObject **obj)
752{ PyTRY
753    if (PyString_Check(*obj)) {
754      *i = Value_str(*(TPyValue **)i);
755      if (!*i)
756        return -1;
757      Py_INCREF(*obj);
758      return 0;
759    }
760
761    if (PyInt_Check(*obj)) {
762      TPyValue *val = *(TPyValue **)i;
763      if (val->value.varType==TValue::INTVAR) {
764        *i = Value_int(val);
765        if (!*i)
766          return -1;
767        Py_INCREF(*obj);
768        return 0;
769      }
770      else if (val->value.varType==TValue::FLOATVAR) {
771        *i = Value_float(val);
772        if (!*i)
773          return -1;
774        double x = PyFloat_AsDouble(*obj);
775            *obj = PyFloat_FromDouble(x);
776        return 0;
777      }
778      else
779        return -1;
780    }
781
782    if (PyFloat_Check(*obj)) {
783      *i = Value_float(*(TPyValue **)i);
784      if (!*i)
785        return -1;
786      Py_INCREF(*obj);
787      return 0;
788    }
789
790    if (PyLong_Check(*obj)) {
791      *i = Value_long(*(TPyValue **)i);
792      if (!*i)
793        return -1;
794      Py_INCREF(*obj);
795      return 0;
796    }
797
798    return -1;
799  PyCATCH_1
800}
801
802
803
804PyObject *Value_get_svalue(TPyValue *self)
805{ PyTRY
806    if (self->value.varType == PYTHONVAR) {
807      PyObject *res = self->value.svalV ? ((TPythonValue &)(self->value.svalV.getReference())).value : Py_None;
808      Py_INCREF(res);
809      return res;
810    }
811
812    return WrapOrange(self->value.svalV);
813  PyCATCH
814}
815
816
817int Value_set_svalue(TPyValue *self, PyObject *arg)
818{ PyTRY
819
820    if (arg == Py_None) {
821      self->value.svalV = PSomeValue();
822      return 0;
823    }
824
825    if (PyOrSomeValue_Check(arg)) {
826      self->value.svalV = PyOrange_AsSomeValue(arg);
827      return 0;
828    }
829
830    self->value.svalV = mlnew TPythonValue(arg);
831    return 0;
832
833  PyCATCH_1
834}
835
836
837PyObject *Value_get_value(TPyValue *self)
838{ PyTRY
839    return convertToPythonNative(self);
840  PyCATCH
841}
842
843
844int Value_set_value(TPyValue *self, PyObject *arg)
845{ PyTRY
846    return convertFromPython(arg, self->value, self->variable) ? 0 : -1;
847  PyCATCH_1
848}
849
850
851PyObject *PyValue_Type_FromLong(long);
852
853PyObject *Value_get_valueType(TPyValue *self)
854{ return PyValue_Type_FromLong((long)self->value.valueType); }
855
856
857PyObject *Value_get_variable(TPyValue *self)
858{ return WrapOrange(self->variable); }
859
860
861int Value_set_variable(TPyValue *self, PyObject *arg)
862{ PyTRY
863    if (arg == Py_None) {
864      self->variable = PVariable();
865      return 0;
866    }
867    if (!PyOrVariable_Check(arg))
868      PYERROR(PyExc_TypeError, "invalid argument for attribute 'variable'", -1)
869    else {
870      self->variable = PyOrange_AsVariable(arg);
871      return 0;
872    }
873  PyCATCH_1
874}
875
876
877PyObject *PyVariable_Type_FromLong(long);
878
879PyObject *Value_get_varType(TPyValue *self)
880{ return PyVariable_Type_FromLong((long)self->value.varType); }
881
882
883
884
885char *value_underscores[][2] = {
886    {"firstvalue", "first_value"},
887    {"nextvalue", "next_value"},
888    {"randomvalue", "random_value"},
889    {"isDC", "is_DC"},
890    {"isDK", "is_DK"},
891    {"isSpecial", "is_special"},
892    {"varType", "var_type"},
893    {"valueType", "value_type"},   
894    {NULL, NULL}
895};
896
897PyObject *Value_getattr(PyObject *self, PyObject *name)
898{
899  char *orig = PyString_AsString(name);
900  for(char *(*ei)[2] = value_underscores; **ei; ei++) {
901      if (!strcmp(orig, **ei)) {
902          PyObject *trans = PyString_FromString((*ei)[1]);
903          PyObject *value = PyObject_GenericGetAttr((PyObject *)self, trans);
904          Py_DECREF(trans);
905          return value;
906      }
907  }
908
909  return PyObject_GenericGetAttr((PyObject *)self, name);
910
911}
912
913PyObject *Value_random_value(TPyValue *self) PYARGS(METH_NOARGS, "(); Sets the value to a random")
914{ PyTRY
915    CHECK_VARIABLE
916    self->value = self->variable->randomValue();
917    RETURN_NONE
918  PyCATCH
919}
920
921
922PyObject *Value_first_value(TPyValue *self)  PYARGS(METH_NOARGS, "() -> bool; Sets the value to the first value")
923{ PyTRY
924    CHECK_VARIABLE
925    return PyInt_FromLong(self->variable->firstValue(self->value) ? 1 : 0);
926  PyCATCH
927}
928
929
930PyObject *Value_next_value(TPyValue *self)  PYARGS(METH_NOARGS, "() -> bool; Increases the value (if possible)")
931{ PyTRY
932    CHECK_VARIABLE
933    return PyInt_FromLong(self->variable->nextValue(self->value) ? 1 : 0);
934  PyCATCH
935}
936
937
938PyObject *Value_isSpecial(TPyValue *self)  PYARGS(METH_NOARGS, "() -> bool; Returns true if value is DK, DC...")
939{ return PyInt_FromLong(self->value.isSpecial() ? 1 : 0); }
940
941
942PyObject *Value_isDK(TPyValue *self)  PYARGS(METH_NOARGS, "() -> bool; Returns true if value is DK")
943{ return PyInt_FromLong(self->value.isDK() ? 1 : 0); }
944
945
946PyObject *Value_isDC(TPyValue *self)  PYARGS(METH_NOARGS, "() -> bool; Returns true if value is DC")
947{ return PyInt_FromLong(self->value.isDC() ? 1 : 0); }
948
949
950PyObject *Value_native(TPyValue *self)   PYARGS(METH_NOARGS, "() -> bool; Converts the value into string or float")
951{ PyTRY
952    return convertToPythonNative(self);
953  PyCATCH
954}
955
956
957#include "slist.hpp"
958
959bool Value_pack(const TValue &value, TCharBuffer &buf, PyObject *&otherValues)
960{
961  const char svalFlag = value.svalV ? 1 << 5 : 0;
962  if (svalFlag) {
963    if (!otherValues)
964      otherValues = PyList_New(0);
965    PyObject *sv = WrapOrange(value.svalV);
966    PyList_Append(otherValues, sv);
967    Py_DECREF(sv);
968  }
969
970  if (value.valueType) {
[8937]971    buf.writeChar(svalFlag | (value.valueType & 0x1f));
[8265]972    return true;
973  }
974
975  if (value.varType == TValue::INTVAR) {
976    if (value.intV < (1 << (sizeof(char) << 3))) {
977      buf.writeChar((1 << 6) | svalFlag);
978      buf.writeChar(char(value.intV));
979    }
980
981    else if (value.intV < (1 << (sizeof(short) << 3))) {
982      buf.writeChar((2 << 6) | svalFlag);
983      buf.writeShort((unsigned short)(value.intV));
984    }
985
986    else {
987      buf.writeChar((3 << 6) | svalFlag);
988      buf.writeInt(value.intV);
989    }
990
991    return true;
992  }
993
994  else if (value.varType == TValue::FLOATVAR) {
995    buf.writeChar(svalFlag);
996    buf.writeFloat(value.floatV);
997  }
998
999  else
1000    buf.writeChar(svalFlag);
1001
1002  return true;
1003}
1004
1005
1006bool Value_unpack(TValue &value, TCharBuffer &buf, PyObject *otherValues, int &otherValuesIndex)
1007{
[8129]1008  unsigned char flags = (unsigned char) buf.readChar();
[8265]1009
1010  if (flags & (1 << 5))
1011    value.svalV = PyOrange_AsSomeValue(PyList_GetItem(otherValues, otherValuesIndex++));
1012
1013  value.valueType = flags & 0x1f;
1014
1015  if (value.valueType) {
1016    value.floatV = numeric_limits<float>::quiet_NaN();
1017    value.intV = numeric_limits<int>::max();
1018    return true;
1019  }
1020
1021  if (value.varType == TValue::INTVAR) {
1022    flags >>= 6;
1023    if (flags == 1)
[8129]1024      value.intV = (unsigned char) buf.readChar();
[8265]1025    else if (flags == 2)
1026      value.intV = buf.readShort();
1027    else if (flags == 3)
1028      value.intV = buf.readInt();
1029    value.floatV = numeric_limits<float>::quiet_NaN();
1030  }
1031
1032  else if (value.varType == TValue::FLOATVAR) {
1033    value.floatV = buf.readFloat();
1034    value.intV = numeric_limits<int>::max();
1035  }
1036   
1037  return true;
1038}
1039
1040PyObject *Value__reduce__(PyObject *self)
1041{
1042  PyTRY
1043    TCharBuffer buf(16);
1044    PyObject *otherValues = NULL;
1045    buf.writeChar(PyValue_AS_Value(self).varType);
1046    Value_pack(PyValue_AS_Value(self), buf, otherValues);
1047    if (!otherValues) {
1048      otherValues = Py_None;
1049      Py_INCREF(otherValues);
1050    }
1051   
1052    return Py_BuildValue("O(Ns#N)", getExportedFunction("__pickleLoaderValue"),
1053                                   WrapOrange(PyValue_AS_Variable(self)),
1054                                   buf.buf, buf.length(),
1055                                   otherValues);
1056  PyCATCH
1057}
1058
1059
1060PyObject *__pickleLoaderValue(PyObject *, PyObject *args) PYARGS(METH_VARARGS, "(variable, packed_values, other_values)")
1061{
1062  PyTRY
1063    PVariable var;
1064    char *pbuf;
1065    int bufSize;
1066    PyObject *otherValues;
1067    if (!PyArg_ParseTuple(args, "O&s#O:__pickleLoaderValue", ccn_Variable, &var, &pbuf, &bufSize, &otherValues))
1068      return PYNULL;
1069
1070    TCharBuffer buf(pbuf);
1071    int otherValuesIndex = 0;
1072    TValue val((const unsigned char &)(buf.readChar()));
1073    Value_unpack(val, buf, otherValues, otherValuesIndex);
1074    return Value_FromVariableValue(var, val);
1075  PyCATCH
1076}
1077
1078#undef CHECK_VARIABLE
1079#undef CHECK_SPECIAL_OTHER
1080
1081
1082// This is in a separate file to avoid scanning by pyxtract
1083#include "valuelisttemplate.hpp"
1084
1085// Modified new and related stuff, removed rich_cmp (might be added later, but needs to be programmed specifically)
1086PValueList PValueList_FromArguments(PyObject *arg, PVariable var = PVariable())
1087{ return TValueListMethods::P_FromArguments(arg, var); }
1088
1089
1090PyObject *ValueList_FromArguments(PyTypeObject *type, PyObject *arg, PVariable var = PVariable())
1091{ return TValueListMethods::_FromArguments(type, arg, var); }
1092
1093
1094PyObject *ValueList_new(PyTypeObject *type, PyObject *arg, PyObject *kwds) BASED_ON(Orange, "(<list of Value>)")  ALLOWS_EMPTY
1095{ return TValueListMethods::_new(type, arg, kwds); }
1096
1097
1098PyObject *ValueList_getitem_sq(TPyOrange *self, Py_ssize_t index) { return TValueListMethods::_getitem(self, index); }
1099int       ValueList_setitem_sq(TPyOrange *self, Py_ssize_t index, PyObject *item) { return TValueListMethods::_setitem(self, index, item); }
1100PyObject *ValueList_getslice(TPyOrange *self, Py_ssize_t start, Py_ssize_t stop) { return TValueListMethods::_getslice(self, start, stop); }
1101int       ValueList_setslice(TPyOrange *self, Py_ssize_t start, Py_ssize_t stop, PyObject *item) { return TValueListMethods::_setslice(self, start, stop, item); }
1102Py_ssize_t ValueList_len_sq(TPyOrange *self) { return TValueListMethods::_len(self); }
1103PyObject *ValueList_concat(TPyOrange *self, PyObject *obj) { return TValueListMethods::_concat(self, obj); }
1104PyObject *ValueList_repeat(TPyOrange *self, Py_ssize_t times) { return TValueListMethods::_repeat(self, times); }
1105PyObject *ValueList_str(TPyOrange *self) { return TValueListMethods::_str(self); }
1106PyObject *ValueList_repr(TPyOrange *self) { return TValueListMethods::_str(self); }
1107int       ValueList_contains(TPyOrange *self, PyObject *obj) { return TValueListMethods::_contains(self, obj); }
1108PyObject *ValueList_append(TPyOrange *self, PyObject *item) PYARGS(METH_O, "(Value) -> None") { return TValueListMethods::_append(self, item); }
1109PyObject *ValueList_extend(TPyOrange *self, PyObject *obj) PYARGS(METH_O, "(sequence) -> None") { return TValueListMethods::_extend(self, obj); }
1110PyObject *ValueList_count(TPyOrange *self, PyObject *obj) PYARGS(METH_O, "(Value) -> int") { return TValueListMethods::_count(self, obj); }
1111PyObject *ValueList_filter(TPyOrange *self, PyObject *args) PYARGS(METH_VARARGS, "([filter-function]) -> ValueList") { return TValueListMethods::_filter(self, args); }
1112PyObject *ValueList_index(TPyOrange *self, PyObject *obj) PYARGS(METH_O, "(Value) -> int") { return TValueListMethods::_index(self, obj); }
1113PyObject *ValueList_insert(TPyOrange *self, PyObject *args) PYARGS(METH_VARARGS, "(index, item) -> None") { return TValueListMethods::_insert(self, args); }
1114PyObject *ValueList_native(TPyOrange *self) PYARGS(METH_NOARGS, "() -> list") { return TValueListMethods::_native(self); }
1115PyObject *ValueList_pop(TPyOrange *self, PyObject *args) PYARGS(METH_VARARGS, "() -> Value") { return TValueListMethods::_pop(self, args); }
1116PyObject *ValueList_remove(TPyOrange *self, PyObject *obj) PYARGS(METH_O, "(Value) -> None") { return TValueListMethods::_remove(self, obj); }
1117PyObject *ValueList_reverse(TPyOrange *self) PYARGS(METH_NOARGS, "() -> None") { return TValueListMethods::_reverse(self); }
1118PyObject *ValueList_sort(TPyOrange *self, PyObject *args) PYARGS(METH_VARARGS, "([cmp-func]) -> None") { return TValueListMethods::_sort(self, args); }
1119PyObject *ValueList__reduce__(TPyOrange *self, PyObject *) { return TValueListMethods::_reduce(self); }
1120
1121
1122
1123PyObject *VarTypes()
1124{ PyObject *vartypes=PyModule_New("Orange.data.Type");
1125  PyModule_AddObject(vartypes, "None", PyVariable_Type_FromLong((int)TValue::NONE));
1126  PyModule_AddObject(vartypes, "Discrete", PyVariable_Type_FromLong((int)TValue::INTVAR));
1127  PyModule_AddObject(vartypes, "Continuous", PyVariable_Type_FromLong((int)TValue::FLOATVAR));
1128  PyModule_AddObject(vartypes, "Other", PyVariable_Type_FromLong((int)TValue::FLOATVAR+1)); // for compatibility; don't use!
1129  PyModule_AddObject(vartypes, "String", PyVariable_Type_FromLong((int)STRINGVAR));
1130  return vartypes;
1131}
1132
1133/* Left here for compatibility */
1134
1135PYCONSTANTFUNC(VarTypes, VarTypes)
1136
1137/* This cannot be done in the header since Value is not derived from Orange */
1138
1139TNamedConstantsDef Value_Type_values[] = {{"Regular", 0}, {"DC", valueDC}, {"DK", valueDK}, {0, 0}};
1140
1141PYXTRACT_IGNORE static PyObject *Value_Type_repr(PyObject *self)
1142{
1143  return stringFromList(self, Value_Type_values);
1144}
1145
1146PYXTRACT_IGNORE PyObject *Value_Type__reduce__(PyObject *self);
1147PyMethodDef Value_Type_methods[] = { {"__reduce__", (binaryfunc)Value_Type__reduce__, METH_NOARGS, "reduce"}, {NULL, NULL}};
1148PyTypeObject PyValue_Type_Type = {PyObject_HEAD_INIT(&PyType_Type) 0, "Value.Type", sizeof(PyIntObject), 0, 0, 0, 0, 0, 0, (reprfunc)Value_Type_repr, 0, 0, 0, 0, 0, (reprfunc)Value_Type_repr, 0, 0, 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, 0, 0, 0, 0, 0, 0, 0, Value_Type_methods, 0, 0, &PyInt_Type};
1149
1150PyObject *PyValue_Type_FromLong(long ok)
1151{ PyIntObject *r = PyObject_New(PyIntObject, &PyValue_Type_Type);
1152  r->ob_ival = ok;
1153  return (PyObject *)r;
1154}
1155
1156void *PTValue_Type(void *l)
1157{ return PyValue_Type_FromLong(*(long *)l); }
1158
1159
1160PYXTRACT_IGNORE PyObject *Value_Type__reduce__(PyObject *self)
1161{ return Py_BuildValue("O(i)", getExportedFunction("__pickleLoaderValueType"), ((PyIntObject *)(self))->ob_ival); }
1162
1163PyObject *__pickleLoaderValueType(PyObject *, PyObject *args) PYARGS(METH_O, "")
1164{ return PyValue_Type_FromLong(PyInt_AsLong(args)); }
1165
1166/* Left for backward compatibility; also used the opportunity to initialize the type */
1167
1168PyObject *ValueTypes()
1169{ PyType_Ready(&PyValue_Type_Type);
1170  PyValue_Type_Type.tp_print = 0;
1171  PyObject *valuetypes=PyModule_New("ValueTypes");
1172  PyModule_AddObject(valuetypes, "Regular", PyValue_Type_FromLong(valueRegular));
1173  PyModule_AddObject(valuetypes, "DC", PyValue_Type_FromLong(valueDC));
1174  PyModule_AddObject(valuetypes, "DK", PyValue_Type_FromLong(valueDK));
1175  return valuetypes;
1176}
1177
1178PYCONSTANTFUNC(ValueTypes, ValueTypes)
1179
1180PYCLASSCONSTANT(Value, Regular, PyValue_Type_FromLong(valueRegular))
1181PYCLASSCONSTANT(Value, DC, PyValue_Type_FromLong(valueDC))
1182PYCLASSCONSTANT(Value, DK, PyValue_Type_FromLong(valueDK))
1183
1184#include "cls_value.px"
Note: See TracBrowser for help on using the repository browser.