variant variant::operator/(const variant& v) const { if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) { int denominator = v.as_decimal(); if(denominator == 0) { throw type_error((formatter() << "divide by zero error").str()); } long long long_int = as_decimal(); long_int *= 10000; long_int /= denominator; if( long_int%10 >= 5) { long_int /= 10; ++long_int; } else long_int/=10; return variant( static_cast<int>(long_int) , variant::DECIMAL_VARIANT); } const int numerator = as_int(); const int denominator = v.as_int(); if(denominator == 0) { throw type_error((formatter() << "divide by zero error").str());; } return variant(numerator/denominator); }
bool variant::operator==(const variant& v) const { if(type_ != v.type_) { if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) { return as_decimal() == v.as_decimal(); } return false; } switch(type_) { case TYPE_NULL: { return v.is_null(); } case TYPE_STRING: { return string_->str == v.string_->str; } case TYPE_INT: { return int_value_ == v.int_value_; } case TYPE_DECIMAL: { return decimal_value_ == v.decimal_value_; } case TYPE_LIST: { if(num_elements() != v.num_elements()) { return false; } for(size_t n = 0; n != num_elements(); ++n) { if((*this)[n] != v[n]) { return false; } } return true; } case TYPE_MAP: { return map_->elements == v.map_->elements; } case TYPE_CALLABLE_LOADING: { return false; } case TYPE_CALLABLE: { return callable_->equals(v.callable_); } case TYPE_FUNCTION: { return fn_ == v.fn_; } } assert(false); return false; }
variant variant::operator*(const variant& v) const { if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) { return variant(as_decimal() * v.as_decimal()); } if(type_ == TYPE_LIST) { int ncopies = v.as_int(); if(ncopies < 0) { ncopies *= -1; } const std::vector<variant>& items = list_->elements; std::vector<variant> res; res.reserve(items.size()*ncopies); for(int n = 0; n != ncopies; ++n) { for(int m = 0; m != items.size(); ++m) { res.push_back(items[m]); } } return variant(&res); } return variant(as_int() * v.as_int()); }
variant variant::operator-(const variant& v) const { if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) { return variant( as_decimal() - v.as_decimal() , DECIMAL_VARIANT); } return variant(as_int() - v.as_int()); }
bool variant::operator<=(const variant& v) const { if(type_ != v.type_) { if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) { return as_decimal() <= v.as_decimal(); } return type_ < v.type_; } switch(type_) { case TYPE_NULL: { return true; } case TYPE_STRING: { return string_->str <= v.string_->str; } case TYPE_INT: { return int_value_ <= v.int_value_; } case TYPE_DECIMAL: { return decimal_value_ <= v.decimal_value_; } case TYPE_LIST: { for(size_t n = 0; n != num_elements() && n != v.num_elements(); ++n) { if((*this)[n] < v[n]) { return true; } else if((*this)[n] > v[n]) { return false; } } return num_elements() <= v.num_elements(); } case TYPE_MAP: { return map_->elements <= v.map_->elements; } case TYPE_CALLABLE_LOADING: { return false; } case TYPE_CALLABLE: { return !v.callable_->less(callable_); } } assert(false); return false; }
variant variant::operator^(const variant& v) const { if( type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL ) { double res = pow( as_decimal().value()/double(VARIANT_DECIMAL_PRECISION), v.as_decimal().value()/double(VARIANT_DECIMAL_PRECISION)); res *= DECIMAL_PRECISION; #if defined(TARGET_BLACKBERRY) return variant(static_cast<int64_t>(llround(res)), DECIMAL_VARIANT); #else return variant(static_cast<int64_t>(res), DECIMAL_VARIANT); #endif } return variant(static_cast<int>(pow(static_cast<double>(as_int()), v.as_int()))); }
variant variant::operator/(const variant& v) const { if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) { if(v.as_decimal().value() == 0) { throw type_error((formatter() << "divide by zero error").str()); } return variant(as_decimal() / v.as_decimal()); } const int numerator = as_int(); const int denominator = v.as_int(); if(denominator == 0) { throw type_error(formatter() << "divide by zero error"); } return variant(numerator/denominator); }
variant variant::operator^(const variant& v) const { if( type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL ) { double res = pow( as_decimal()/1000.0 , v.as_decimal()/1000.0 ); res *= 1000; int i = static_cast<int>( res ); res -= i; if( res > 0.5 ) i++; return variant( i , variant::DECIMAL_VARIANT); } return variant(static_cast<int>( round_portable(pow(static_cast<double>(as_int()), v.as_int())))); }
variant variant::operator*(const variant& v) const { if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) { long long long_int = as_decimal(); long_int *= v.as_decimal(); long_int /= 100; if( long_int%10 >= 5) { long_int /= 10; ++long_int; } else long_int/=10; return variant( static_cast<int>(long_int) , variant::DECIMAL_VARIANT ); } return variant(as_int() * v.as_int()); }
variant variant::operator+(const variant& v) const { if(type_ == TYPE_LIST) { if(v.type_ == TYPE_LIST) { std::vector<variant> res; res.reserve(list_->elements.size() + v.list_->elements.size()); for(size_t i = 0; i<list_->elements.size(); ++i) { const variant& var = list_->elements[i]; res.push_back(var); } for(size_t j = 0; j<v.list_->elements.size(); ++j) { const variant& var = v.list_->elements[j]; res.push_back(var); } return variant(&res); } } if(type_ == TYPE_MAP) { if(v.type_ == TYPE_MAP) { std::map<variant,variant> res(map_->elements); for(std::map<variant,variant>::const_iterator i = v.map_->elements.begin(); i != v.map_->elements.end(); ++i) { res[i->first] = i->second; } return variant(&res); } } if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) { return variant( as_decimal() + v.as_decimal() , DECIMAL_VARIANT); } return variant(as_int() + v.as_int()); }
variant variant::operator+(const variant& v) const { if(type_ == TYPE_INT && v.type_ == TYPE_INT) { //strictly an optimization -- this is handled below, but the case //of adding two integers is the most common so we want it to be fast. return variant(int_value_ + v.int_value_); } if(type_ == TYPE_STRING) { if(v.type_ == TYPE_MAP) { return variant(as_string() + v.as_string()); } else if(v.type_ == TYPE_STRING) { return variant(as_string() + v.as_string()); } std::string s; v.serialize_to_string(s); return variant(as_string() + s); } if(v.type_ == TYPE_STRING) { std::string s; serialize_to_string(s); return variant(s + v.as_string()); } if(type_ == TYPE_DECIMAL || v.type_ == TYPE_DECIMAL) { return variant(as_decimal() + v.as_decimal()); } if(type_ == TYPE_INT) { return variant(int_value_ + v.as_int()); } if(type_ == TYPE_NULL) { return v; } else if(v.type_ == TYPE_NULL) { return *this; } if(type_ == TYPE_LIST) { if(v.type_ == TYPE_LIST) { std::vector<variant> res; res.reserve(list_->elements.size() + v.list_->elements.size()); for(size_t i = 0; i<list_->elements.size(); ++i) { const variant& var = list_->elements[i]; res.push_back(var); } for(size_t j = 0; j<v.list_->elements.size(); ++j) { const variant& var = v.list_->elements[j]; res.push_back(var); } return variant(&res); } } if(type_ == TYPE_MAP) { if(v.type_ == TYPE_MAP) { std::map<variant,variant> res(map_->elements); for(std::map<variant,variant>::const_iterator i = v.map_->elements.begin(); i != v.map_->elements.end(); ++i) { res[i->first] = i->second; } return variant(&res); } } return variant(as_int() + v.as_int()); }