/// <summary> /// Applies the Sum Aggregate function to the results /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingIDs">Binding IDs over which the Aggregate applies</param> /// <returns></returns> public override INode Apply(SparqlEvaluationContext context, IEnumerable <int> bindingIDs) { if (this._varname != null) { //Ensured the SUMmed variable is in the Variables of the Results if (!context.Binder.Variables.Contains(this._varname)) { throw new RdfQueryException("Cannot use the Variable " + this._expr.ToString() + " in a SUM Aggregate since the Variable does not occur in a Graph Pattern"); } } //Prep Variables long lngtotal = 0; decimal dectotal = 0.0m; float flttotal = 0.0f; double dbltotal = 0.0d; SparqlNumericType maxtype = SparqlNumericType.NaN; if (!(this._expr is ISparqlNumericExpression)) { throw new RdfQueryException("Cannot calculate an sum aggregate over a non-numeric expression"); } ISparqlNumericExpression numExpr = (ISparqlNumericExpression)this._expr; SparqlNumericType numtype; HashSet <INode> values = new HashSet <INode>(); foreach (int id in bindingIDs) { try { if (this._distinct) { INode temp = this._expr.Value(context, id); if (temp == null) { continue; } if (values.Contains(temp)) { continue; } else { values.Add(temp); } } numtype = numExpr.NumericType(context, id); } catch { continue; } //Skip if Not a Number if (numtype == SparqlNumericType.NaN) { continue; } //Track the Numeric Type if ((int)numtype > (int)maxtype) { maxtype = numtype; } //Increment the Totals based on the current Numeric Type switch (maxtype) { case SparqlNumericType.Integer: lngtotal += numExpr.IntegerValue(context, id); dectotal += numExpr.DecimalValue(context, id); flttotal += numExpr.FloatValue(context, id); dbltotal += numExpr.DoubleValue(context, id); break; case SparqlNumericType.Decimal: dectotal += numExpr.DecimalValue(context, id); flttotal += numExpr.FloatValue(context, id); dbltotal += numExpr.DoubleValue(context, id); break; case SparqlNumericType.Float: flttotal += numExpr.FloatValue(context, id); dbltotal += numExpr.DoubleValue(context, id); break; case SparqlNumericType.Double: dbltotal += numExpr.DoubleValue(context, id); break; } } //Return the Sum switch (maxtype) { case SparqlNumericType.NaN: //No Numeric Values return(new LiteralNode(null, "0", new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger))); case SparqlNumericType.Integer: //Integer Values return(new LiteralNode(null, lngtotal.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger))); case SparqlNumericType.Decimal: //Decimal Values return(new LiteralNode(null, dectotal.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDecimal))); case SparqlNumericType.Float: //Float Values return(new LiteralNode(null, flttotal.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeFloat))); case SparqlNumericType.Double: //Double Values return(new LiteralNode(null, dbltotal.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDouble))); default: throw new RdfQueryException("Failed to calculate a valid Sum"); } }
/// <summary> /// Applies the Numeric Min Aggregate function to the results /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingIDs">Binding IDs over which the Aggregate applies</param> /// <returns></returns> public override INode Apply(SparqlEvaluationContext context, IEnumerable <int> bindingIDs) { if (this._varname != null) { //Ensured the MINed variable is in the Variables of the Results if (!context.Binder.Variables.Contains(this._varname)) { throw new RdfQueryException("Cannot use the Variable " + this._expr.ToString() + " in a NMIN Aggregate since the Variable does not occur in a Graph Pattern"); } } //Prep Variables long lngmin = 0; decimal decmin = 0.0m; float fltmin = 0.0f; double dblmin = 0.0d; SparqlNumericType mintype = SparqlNumericType.NaN; if (!(this._expr is ISparqlNumericExpression)) { throw new RdfQueryException("Cannot evaluate a NMIN aggregate over a non-numeric expression"); } ISparqlNumericExpression numExpr = (ISparqlNumericExpression)this._expr; SparqlNumericType numtype; foreach (int id in bindingIDs) { try { numtype = numExpr.NumericType(context, id); } catch { continue; } //Skip if Not a Number if (numtype == SparqlNumericType.NaN) { continue; } //Track the Numeric Type if ((int)numtype > (int)mintype) { if (mintype == SparqlNumericType.NaN) { //Initialise Minimums switch (numtype) { case SparqlNumericType.Integer: lngmin = numExpr.IntegerValue(context, id); decmin = numExpr.DecimalValue(context, id); fltmin = numExpr.FloatValue(context, id); dblmin = numExpr.DoubleValue(context, id); break; case SparqlNumericType.Decimal: decmin = numExpr.DecimalValue(context, id); fltmin = numExpr.FloatValue(context, id); dblmin = numExpr.DoubleValue(context, id); break; case SparqlNumericType.Float: fltmin = numExpr.FloatValue(context, id); dblmin = numExpr.DoubleValue(context, id); break; case SparqlNumericType.Double: dblmin = numExpr.DoubleValue(context, id); break; } mintype = numtype; continue; } else { mintype = numtype; } } long lngval; decimal decval; float fltval; double dblval; switch (mintype) { case SparqlNumericType.Integer: lngval = numExpr.IntegerValue(context, id); if (lngval < lngmin) { lngmin = lngval; decmin = numExpr.DecimalValue(context, id); fltmin = numExpr.FloatValue(context, id); dblmin = numExpr.DoubleValue(context, id); } break; case SparqlNumericType.Decimal: decval = numExpr.DecimalValue(context, id); if (decval < decmin) { decmin = decval; fltmin = numExpr.FloatValue(context, id); dblmin = numExpr.DoubleValue(context, id); } break; case SparqlNumericType.Float: fltval = numExpr.FloatValue(context, id); if (fltval < fltmin) { fltmin = fltval; dblmin = numExpr.DoubleValue(context, id); } break; case SparqlNumericType.Double: dblval = numExpr.DoubleValue(context, id); if (dblval < dblmin) { dblmin = dblval; } break; } } //Return the Min switch (mintype) { case SparqlNumericType.NaN: //No Numeric Values return(null); case SparqlNumericType.Integer: //Integer Values return(new LiteralNode(null, lngmin.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeInteger))); case SparqlNumericType.Decimal: //Decimal Values return(new LiteralNode(null, decmin.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDecimal))); case SparqlNumericType.Double: //Double Values return(new LiteralNode(null, dblmin.ToString(), new Uri(XmlSpecsHelper.XmlSchemaDataTypeDouble))); default: throw new RdfQueryException("Failed to calculate a valid Minimum"); } }
/// <summary> /// Calculates the Numeric Value of this Expression as evaluated for a given Binding /// </summary> /// <param name="context">Evaluation Context</param> /// <param name="bindingID">Binding ID</param> /// <returns></returns> public override Object NumericValue(SparqlEvaluationContext context, int bindingID) { if (this._expr is ISparqlNumericExpression) { ISparqlNumericExpression a = (ISparqlNumericExpression)this._expr; switch (a.NumericType(context, bindingID)) { case SparqlNumericType.Integer: return(-1 * a.IntegerValue(context, bindingID)); case SparqlNumericType.Decimal: decimal decvalue = a.DecimalValue(context, bindingID); if (decvalue == 0) { return(0.0m); } else { return(-1 * decvalue); } case SparqlNumericType.Float: float fltvalue = a.FloatValue(context, bindingID); if (Single.IsNaN(fltvalue)) { return(Single.NaN); } else if (Single.IsPositiveInfinity(fltvalue)) { return(Single.NegativeInfinity); } else if (Single.IsNegativeInfinity(fltvalue)) { return(Single.PositiveInfinity); } else { return(-1.0 * fltvalue); } case SparqlNumericType.Double: double dblvalue = a.DoubleValue(context, bindingID); if (Double.IsNaN(dblvalue)) { return(Double.NaN); } else if (Double.IsPositiveInfinity(dblvalue)) { return(Double.NegativeInfinity); } else if (Double.IsNegativeInfinity(dblvalue)) { return(Double.PositiveInfinity); } else { return(-1.0 * dblvalue); } default: throw new RdfQueryException("Cannot evalute an Arithmetic Expression when the Numeric Type of the expression cannot be determined"); } } else { throw new RdfQueryException("Cannot evalute an Arithmetic Expression where the sub-expression is not a Numeric Expressions"); } }