⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cls_value.cpp

📁 orange源码 数据挖掘技术
💻 CPP
📖 第 1 页 / 共 3 页
字号:
}


int Value_traverse(TPyValue *self, visitproc visit, void *arg)
{ PVISIT(self->variable);
  PVISIT(self->value.svalV);
  return 0;
}


void Value_clear(TPyValue *self)
{ self->variable=PVariable();
  self->value.~TValue();
}


/* Returns a string representations for a value.
   - If descriptor is given, its val2str should take care of everything
   - If the value is special, we know that to do
   - If value is 
     - FLOATVAR, convert a floatV
     - INTVAR, print a intV in brackets
     - else if svalV is given, it should take care of itself
     - else, we return "###"
*/

char *pvs = NULL;
const char *TPyValue2string(TPyValue *self)
{ if (self->variable) {
    string str;
    self->variable->val2str(self->value, str);
    pvs = (char *)realloc(pvs, str.size()+1);
    strcpy(pvs, str.c_str());
  }
  else {
    if (self->value.isDK())
      return "?";
    if (self->value.isDC())
      return "~";
    if (self->value.isSpecial())
      return ".";

    pvs = (char *)realloc(pvs, 16);
    if (self->value.varType==TValue::FLOATVAR)
      sprintf(pvs, "%f", self->value.floatV);
    else if (self->value.varType==TValue::INTVAR)
      sprintf(pvs, "<%i>", self->value.intV);
    else if (self->value.svalV) {
      string str;
      self->value.svalV->val2str(str);
      pvs = (char *)realloc(pvs, str.size()+1);
      strcpy(pvs, str.c_str());
    }
    else
      return "###";
  }

  return pvs;
}



/* Compares two values. The first is always TPyValue.
   Comparisons of discrete are based on intV not on string representations
   If both are TPyValue, the values must be of same type
     - If both are special, they are equal/different if the valueType is
       equal/different. Operators >, <, <= and >= are not defined.
     - If only one is special, it's an error
     - If they are discrete and descriptors are known but different,
       each value's string representation is compared to the other's,
       both comparisons are made and must give the same result.
       If not, it's an error.
     - Otherwise, intV's r floatV's are compared
   If the other is an integer, it can be compared with discrete and
     continuous attributes
   If the other is a float, it can be compared with continuous attrs.
   If the first value is special and the other is string "~" or "?",
     they are compared as described above.
   Otherwise, the descriptor for the first value must be known and is
     used to convert the second value (if possible). The values are
     then compared by the same rules as if both were PyValues
     (except that both obviously have the same descriptor).
*/

#define errUndefinedIf(cond) if (cond) PYERROR(PyExc_TypeError, "Value.compare: cannot compare with undefined values", PYNULL);

PyObject *richcmp_from_sign(const int &i, const int &op)
{ int cmp;
  switch (op) {
		case Py_LT: cmp = (i<0); break;
		case Py_LE: cmp = (i<=0); break;
		case Py_EQ: cmp = (i==0); break;
		case Py_NE: cmp = (i!=0); break;
		case Py_GT: cmp = (i>0); break;
		case Py_GE: cmp = (i>=0); break;
    default:
      Py_INCREF(Py_NotImplemented);
      return Py_NotImplemented;
  }
  
  PyObject *res;
  if (cmp)
    res = Py_True;
  else
    res = Py_False;
  Py_INCREF(res);
  return res;
}


PyObject *Value_richcmp(TPyValue *i, PyObject *j, int op)
{ 
  PyTRY

    const TValue &val1 = i->value;

    if (PyOrValue_Check(j)) {
      const TValue &val2 = PyValue_AS_Value(j);

      if (val1.varType != val2.varType)
        PYERROR(PyExc_TypeError, "Value.compare: can't compare values of different types", PYNULL)

      if (val1.isSpecial() || val2.isSpecial())
        if ((op==Py_EQ) || (op==Py_NE)) {
          PyObject *res = (val1.valueType==val2.valueType) == (op==Py_EQ) ? Py_True : Py_False;
          Py_INCREF(res);
          return res;
        }
        else {
          Py_INCREF(Py_NotImplemented);
          return Py_NotImplemented;
        }

      // Nominal values of different attributes are treated separately
      PVariable &var1 = i->variable;
      PVariable &var2 = PyValue_AS_Variable(j);
      if ((val1.varType==TValue::INTVAR) && var1 && var2 && (var1 != var2)) {
        TValue tempval;
        string tempstr;

        var2->val2str(val2, tempstr);
        if (var1->str2val_try(tempstr, tempval)) {
          int cmp1 = val1.compare(tempval);

          var1->val2str(val1, tempstr);
          if (var2->str2val_try(tempstr, tempval)) {
            int cmp2 = tempval.compare(val2);
            bool err = true;
            switch (op) {
              case Py_LE:
              case Py_GE: err = ((cmp1*cmp2) == -1); break;
              case Py_LT:
              case Py_GT: err = (cmp1!=cmp2); break;
              case Py_EQ:
              case Py_NE: err = ((cmp1==0) != (cmp2==0)); break;
            }

            if (err)
              PYERROR(PyExc_TypeError, "Value.compare: values are of different types and have different orders", PYNULL);
          }

          return richcmp_from_sign(cmp1, op);
        }

        var1->val2str(val1, tempstr);
        if (var2->str2val_try(tempstr, tempval))
          return richcmp_from_sign(tempval.compare(val2), op);

        PYERROR(PyExc_TypeError, "Value.compare: values are of different types and cannot be compared", PYNULL);
      }

      // Not nominal OR both values or of the same attribute
      return richcmp_from_sign(val1.compare(val2), op);
    }


    if (PyInt_Check(j)) {
      errUndefinedIf(val1.isSpecial());

      if (val1.varType==TValue::INTVAR)
        return richcmp_from_sign(val1.intV - (int)PyInt_AsLong(j), op);
      else if (val1.varType==TValue::FLOATVAR)
        return richcmp_from_sign(sign(val1.floatV - (int)PyInt_AsLong(j)), op);
    }

    else if (PyFloat_Check(j)) {
      errUndefinedIf(val1.isSpecial());
      if (val1.varType==TValue::FLOATVAR)
        return richcmp_from_sign(sign(val1.floatV - (float)PyFloat_AsDouble(j)), op);
    }

    else if (PyString_Check(j) && val1.isSpecial() && ((op==Py_EQ) || (op==Py_NE))) {
      char *s = PyString_AsString(j);
      PyObject *res = NULL;
      if (!strcmp(s, "~"))
        res = (val1.valueType==valueDC) == (op==Py_EQ) ? Py_True : Py_False;
      else if (!strcmp(s, "?"))
        res = (val1.valueType==valueDK) == (op==Py_EQ) ? Py_True : Py_False;
      if (res) {
        Py_INCREF(res);
        return res;
      }
    }

    if (i->variable) {
      TValue val2;
      if (!convertFromPython(j, val2, i->variable))
        return PYNULL;

      if (val1.isSpecial() || val2.isSpecial())
        if ((op==Py_EQ) || (op==Py_NE)) {
          PyObject *res = (val1.valueType==val2.valueType) == (op==Py_EQ) ? Py_True : Py_False;
          Py_INCREF(res);
          return res;
        }
        else {
          Py_INCREF(Py_NotImplemented);
          return Py_NotImplemented;
        }

      return richcmp_from_sign(val1.compare(val2), op);
    }
      
    Py_INCREF(Py_NotImplemented);
    return Py_NotImplemented;

  PyCATCH
}
#undef errUndefinedIf



PyObject *Value_str(TPyValue *self)
{ PyTRY
    return PyString_FromString(TPyValue2string(self)); 
  PyCATCH
}


PyObject *Value_repr(TPyValue *self)
{ PyTRY
    if (self->variable)
      return PyString_FromFormat("<orange.Value '%s'='%s'>", self->variable->name.c_str(), TPyValue2string(self));
    else
      return PyString_FromFormat("<orange.Value '%s'>", TPyValue2string(self)); 
  PyCATCH
}


bool checkSpecial(TPyValue *self, char *casttype)
{
  if (self->value.isSpecial()) {
    if (self->variable && self->variable->name.length())
      PyErr_Format(PyExc_TypeError, "value of '%s' is unknown and cannot be %s", self->variable->name.c_str(), casttype);
    else
      PyErr_Format(PyExc_TypeError, "attribute value is unknown and cannot be %s", casttype);
    return false;
  }

  return true;
}

PyObject *Value_int(TPyValue *self)
{ PyTRY
    if (!checkSpecial(self, "cast to an integer"))
      return PYNULL;

    return Py_BuildValue("i", (self->value.varType==TValue::INTVAR) ? self->value.intV : int(self->value.floatV)); 
  PyCATCH
}


PyObject *Value_long(TPyValue *self)
{ PyTRY
    if (!checkSpecial(self, "cast to a long integer"))
      return PYNULL;

    return Py_BuildValue("l", (self->value.varType==TValue::INTVAR) ? long(self->value.intV) : long(self->value.floatV)); 
  PyCATCH
}


PyObject *Value_float(TPyValue *self)
{ PyTRY
    if (!checkSpecial(self, "cast to a float"))
      return PYNULL;

    return Py_BuildValue("f", (self->value.varType==TValue::INTVAR) ? float(self->value.intV) : self->value.floatV); 
  PyCATCH
}


inline bool checkForNumerical(const TValue &val1, const TValue &val2, const char *op)
{
  if (val1.isSpecial() || val2.isSpecial())
    PYERROR(PyExc_TypeError, "cannot %s unknown values", false);
  if ((val1.varType!=TValue::FLOATVAR) || (val2.varType!=TValue::FLOATVAR))
    PYERROR(PyExc_TypeError, "cannot %s non-continuous values", false);
  return true;
}


#define VALUEOP(opname,FUN,opverb) \
PyObject *Value_##opname(TPyValue *self, PyObject *other) \
{ PyTRY \
    const TValue &val1 = self->value; \
\
    if (PyOrValue_Check(other)) { \
      const TValue &val2 = PyValue_AS_Value(other); \
      return checkForNumerical(val1, val2, opverb) ? PyFloat_FromDouble(val1.floatV FUN val2.floatV) : PYNULL; \
    } \
\
    TValue val2; \
    return convertFromPython(other, val2, self->variable) && checkForNumerical(val1, val2, opverb) ? PyFloat_FromDouble(val1.floatV FUN val2.floatV) : PYNULL; \
  PyCATCH \
}


PyObject *Value_add(TPyValue *self, PyObject *other);
PyObject *Value_sub(TPyValue *self, PyObject *other);
PyObject *Value_mul(TPyValue *self, PyObject *other);
PyObject *Value_div(TPyValue *self, PyObject *other);

VALUEOP(add,+,"sum")
VALUEOP(sub,-,"subtract")
VALUEOP(mul,*,"multiply")
VALUEOP(div,/,"divide")


PyObject *Value_pow(TPyValue *self, PyObject *other, PyObject *)
{ PyTRY
    const TValue &val1 = self->value;
    
    if (!val1.isSpecial() && (val1.varType==TValue::FLOATVAR) && (val1.floatV<=0))
      PYERROR(PyExc_TypeError, "negative base value", false);

    if (PyOrValue_Check(other)) { 
      const TValue &val2 = PyValue_AS_Value(other); 
      return checkForNumerical(val1, val2, "add") ? PyFloat_FromDouble(exp(val2.floatV*log(val1.floatV))) : PYNULL;
    }
    else {
      TValue val2; 
      return    convertFromPython(other, val2, self->variable)
             && checkForNumerical(val1, val2, "add")
           ? PyFloat_FromDouble(exp(val2.floatV*log(val1.floatV)))
           : PYNULL;
    }
  PyCATCH 
}


PyObject *Value_neg(TPyValue *self)
{ PyTRY
    if (!checkSpecial(self, "negated"))
      return PYNULL;

    const TValue &val1 = self->value;
    if (val1.varType!=TValue::FLOATVAR)
      PYERROR(PyExc_TypeError, "cannot negate non-continuous value", false);
    return PyFloat_FromDouble(-val1.floatV);
  PyCATCH
}


PyObject *Value_abs(TPyValue *self)
{ PyTRY
    if (self->value.isSpecial())
      if (self->variable && self->variable->name.length()) {
        PyErr_Format(PyExc_TypeError, "cannot compute an absolute value of '%s' since its value is unknown", self->variable->name.c_str());
        return PYNULL;
      }
      else
        PYERROR(PyExc_TypeError, "cannot compute an absolute value of attribute since its value is unknown", PYNULL);

    const TValue &val1 = self->value;
    if (val1.varType!=TValue::FLOATVAR)
      PYERROR(PyExc_TypeError, "cannot compute abs of non-continuous value", false);
    return PyFloat_FromDouble(fabs(val1.floatV));
  PyCATCH

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -