def generalizeArgAndResultTypesForNumericOp()

in daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/NodeInfoUtils.scala [84:133]


  def generalizeArgAndResultTypesForNumericOp(
    op: String,
    leftArgType: Numeric.Kind,
    rightArgType: Numeric.Kind
  ): ( //
    Numeric.Kind, // first result is generalized arg type
    Numeric.Kind // second result is generalized result type
  ) = {

    /*
     * Adjust for the Decimal result type when div/idiv is used
     */
    def divResult(resultType: NodeInfo.Numeric.Kind) = resultType match {
      case ArrayIndex => ArrayIndex
      case _: Decimal.Kind => Decimal
      case Double => Double
      case Float => Float
      case _ => Assert.usageError("Unsupported return type: %s".format(resultType))
    }

    def idivResult(resultType: NodeInfo.Numeric.Kind) = resultType match {
      case Decimal => Integer
      case Integer => Integer
      case Double => Long
      case Long => Long
      case Float => Int
      case Int => Int
      case Short => Short
      case ArrayIndex => ArrayIndex
      case _ => Assert.usageError("Unsupported return type: %s".format(resultType))
    }

    val (argType: Numeric.Kind, resultType: Numeric.Kind) = {
      val lub = NodeInfoUtils.typeLeastUpperBound(leftArgType, rightArgType)
      //
      // For each abstract type that could be the least upper bound of the two
      // arg types, we must pick a concrete type to convert everything into.
      val lubImplementationType = lub match {
        case SignedNumeric => NodeInfo.Double
        case _ => lub
      }
      (lubImplementationType, lubImplementationType)
    }
    val res = op match {
      case "div" => (argType, divResult(resultType))
      case "idiv" => (argType, idivResult(resultType))
      case _ => (argType, resultType)
    }
    res
  }