• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TouK / nussknacker / 5976637142

25 Aug 2023 01:43PM UTC coverage: 81.47% (+0.03%) from 81.438%
5976637142

push

github

Filemon279
Fix migration in 1.11

25 of 25 new or added lines in 2 files covered. (100.0%)

14865 of 18246 relevant lines covered (81.47%)

5.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.82
/utils/math-utils/src/main/scala/pl/touk/nussknacker/engine/util/MathUtils.scala
1
package pl.touk.nussknacker.engine.util
2

3
import org.springframework.util.{NumberUtils => SpringNumberUtils}
4
import pl.touk.nussknacker.engine.api.typed.supertype.{NumberTypesPromotionStrategy, ReturningSingleClassPromotionStrategy}
5

6
import java.lang
7

8
trait MathUtils {
9

10
  def min(n1: Number, n2: Number): Number = {
11
    implicit val promotionStrategy: ReturningSingleClassPromotionStrategy = NumberTypesPromotionStrategy.ForMinMax
4✔
12
    withNotNullValues(n1, n2) {
4✔
13
      withValuesWithTheSameType(n1, n2)(new SameNumericTypeHandlerReturningNumber {
14
        override def onBytes(n1: java.lang.Byte, n2: java.lang.Byte): java.lang.Byte =
15
          Math.min(n1.intValue(), n2.intValue()).byteValue()
16
        override def onShorts(n1: java.lang.Short, n2: java.lang.Short): java.lang.Short =
17
          Math.min(n1.intValue(), n2.intValue()).shortValue()
18
        override def onInts(n1: java.lang.Integer, n2: java.lang.Integer): java.lang.Integer =
19
          Math.min(n1, n2)
20
        override def onLongs(n1: java.lang.Long, n2: java.lang.Long): java.lang.Long =
21
          Math.min(n1, n2)
22
        override def onBigIntegers(n1: java.math.BigInteger, n2: java.math.BigInteger): java.math.BigInteger =
23
          n1.min(n2)
24
        override def onFloats(n1: java.lang.Float, n2: java.lang.Float): java.lang.Float =
25
          Math.min(n1, n2)
26
        override def onDoubles(n1: java.lang.Double, n2: java.lang.Double): java.lang.Double =
27
          Math.min(n1, n2)
28
        override def onBigDecimals(n1: java.math.BigDecimal, n2: java.math.BigDecimal): java.math.BigDecimal =
29
          n1.min(n2)
30
      })
31
    }
32
  }
33

34
  def max(n1: Number, n2: Number): Number = {
35
    implicit val promotionStrategy: ReturningSingleClassPromotionStrategy = NumberTypesPromotionStrategy.ForMinMax
4✔
36
    withNotNullValues(n1, n2) {
4✔
37
      withValuesWithTheSameType(n1, n2)(new SameNumericTypeHandlerReturningNumber {
38
        override def onBytes(n1: java.lang.Byte, n2: java.lang.Byte): java.lang.Byte =
39
          Math.max(n1.intValue(), n2.intValue()).byteValue()
40
        override def onShorts(n1: java.lang.Short, n2: java.lang.Short): java.lang.Short =
41
          Math.max(n1.intValue(), n2.intValue()).shortValue()
42
        override def onInts(n1: java.lang.Integer, n2: java.lang.Integer): java.lang.Integer =
43
          Math.max(n1, n2)
44
        override def onLongs(n1: java.lang.Long, n2: java.lang.Long): java.lang.Long =
45
          Math.max(n1, n2)
46
        override def onBigIntegers(n1: java.math.BigInteger, n2: java.math.BigInteger): java.math.BigInteger =
47
          n1.max(n2)
48
        override def onFloats(n1: java.lang.Float, n2: java.lang.Float): java.lang.Float =
49
          Math.max(n1, n2)
50
        override def onDoubles(n1: java.lang.Double, n2: java.lang.Double): java.lang.Double =
51
          Math.max(n1, n2)
52
        override def onBigDecimals(n1: java.math.BigDecimal, n2: java.math.BigDecimal): java.math.BigDecimal =
53
          n1.max(n2)
54
      })
55
    }
56
  }
57

58
  def sum(n1: Number, n2: Number): Number = {
59
    implicit val promotionStrategy: ReturningSingleClassPromotionStrategy = NumberTypesPromotionStrategy.ForMathOperation
4✔
60
    promoteThenSum(n1, n2)
4✔
61
  }
62

63
  def largeSum(n1: Number, n2: Number): Number = {
64
    implicit val promotionStrategy: ReturningSingleClassPromotionStrategy = NumberTypesPromotionStrategy.ForLargeNumbersOperation
2✔
65
    promoteThenSum(n1, n2)
2✔
66
  }
67

68
  def plus(n1: Number, n2: Number): Number = sum(n1, n2)
2✔
69

70
  def minus(n1: Number, n2: Number): Number = {
71
    withValuesWithTheSameType(n1, n2)(new SameNumericTypeHandlerForPromotingMathOp {
2✔
72
      override def onInts(n1: java.lang.Integer, n2: java.lang.Integer): java.lang.Integer = n1 - n2
2✔
73
      override def onLongs(n1: java.lang.Long, n2: java.lang.Long): java.lang.Long = n1 - n2
2✔
74
      override def onBigIntegers(n1: java.math.BigInteger, n2: java.math.BigInteger): java.math.BigInteger = n1.subtract(n2)
×
75
      override def onFloats(n1: java.lang.Float, n2: java.lang.Float): java.lang.Float = n1 - n2
2✔
76
      override def onDoubles(n1: java.lang.Double, n2: java.lang.Double): java.lang.Double = n1 - n2
2✔
77
      override def onBigDecimals(n1: java.math.BigDecimal, n2: java.math.BigDecimal): java.math.BigDecimal = n1.subtract(n2)
×
78
    })(NumberTypesPromotionStrategy.ForMathOperation)
2✔
79
  }
80

81
  def multiply(n1: Number, n2: Number): Number = {
82
    withValuesWithTheSameType(n1, n2)(new SameNumericTypeHandlerForPromotingMathOp {
2✔
83
      override def onInts(n1: java.lang.Integer, n2: java.lang.Integer): java.lang.Integer = n1 * n2
2✔
84
      override def onLongs(n1: java.lang.Long, n2: java.lang.Long): java.lang.Long = n1 * n2
2✔
85
      override def onBigIntegers(n1: java.math.BigInteger, n2: java.math.BigInteger): java.math.BigInteger = n1.multiply(n2)
×
86
      override def onFloats(n1: java.lang.Float, n2: java.lang.Float): java.lang.Float = n1 * n2
2✔
87
      override def onDoubles(n1: java.lang.Double, n2: java.lang.Double): java.lang.Double = n1 * n2
2✔
88
      override def onBigDecimals(n1: java.math.BigDecimal, n2: java.math.BigDecimal): java.math.BigDecimal = n1.multiply(n2)
×
89
    })(NumberTypesPromotionStrategy.ForMathOperation)
2✔
90
  }
91

92
  def divide(n1: Number, n2: Number): Number = {
93
    withValuesWithTheSameType(n1, n2)(new SameNumericTypeHandlerForPromotingMathOp {
2✔
94
      override def onInts(n1: java.lang.Integer, n2: java.lang.Integer): java.lang.Integer = n1 / n2
2✔
95
      override def onLongs(n1: java.lang.Long, n2: java.lang.Long): java.lang.Long = n1 / n2
2✔
96
      override def onBigIntegers(n1: java.math.BigInteger, n2: java.math.BigInteger): java.math.BigInteger = n1.divide(n2)
×
97
      override def onFloats(n1: java.lang.Float, n2: java.lang.Float): java.lang.Float = n1 / n2
2✔
98
      override def onDoubles(n1: java.lang.Double, n2: java.lang.Double): java.lang.Double = n1 / n2
2✔
99
      override def onBigDecimals(n1: java.math.BigDecimal, n2: java.math.BigDecimal): java.math.BigDecimal = n1.divide(n2)
×
100
    })(NumberTypesPromotionStrategy.ForMathOperation)
2✔
101
  }
102

103
  def remainder(n1: Number, n2: Number): Number = {
104
    withValuesWithTheSameType(n1, n2)(new SameNumericTypeHandlerForPromotingMathOp {
2✔
105
      override def onInts(n1: java.lang.Integer, n2: java.lang.Integer): java.lang.Integer = n1 % n2
2✔
106
      override def onLongs(n1: java.lang.Long, n2: java.lang.Long): java.lang.Long = n1 % n2
2✔
107
      override def onBigIntegers(n1: java.math.BigInteger, n2: java.math.BigInteger): java.math.BigInteger = n1.remainder(n2)
×
108
      override def onFloats(n1: java.lang.Float, n2: java.lang.Float): java.lang.Float = n1 % n2
2✔
109
      override def onDoubles(n1: java.lang.Double, n2: java.lang.Double): java.lang.Double = n1 % n2
2✔
110
      override def onBigDecimals(n1: java.math.BigDecimal, n2: java.math.BigDecimal): java.math.BigDecimal = n1.remainder(n2)
×
111
    })(NumberTypesPromotionStrategy.ForMathOperation)
2✔
112
  }
113

114
  def negate(n1: Number): Number = n1 match {
115
    case n1: java.lang.Byte => -n1
×
116
    case n1: java.lang.Short => -n1
×
117
    case n1: java.lang.Integer => -n1
6✔
118
    case n1: java.lang.Long => -n1
6✔
119
    case n1: java.math.BigInteger => n1.negate()
×
120
    case n1: java.lang.Float => -n1
×
121
    case n1: java.lang.Double => -n1
4✔
122
    case n1: java.math.BigDecimal => n1.negate()
×
123
  }
124

125
  private def compare(n1: Number, n2: Number): Int = {
126
    withValuesWithTheSameType(n1, n2)(new SameNumericTypeHandler[Int] {
2✔
127
      override def onBytes(n1: java.lang.Byte, n2: java.lang.Byte): Int = n1.compareTo(n2)
×
128
      override def onShorts(n1: java.lang.Short, n2: java.lang.Short): Int = n1.compareTo(n2)
×
129
      override def onInts(n1: java.lang.Integer, n2: java.lang.Integer): Int = n1.compareTo(n2)
2✔
130
      override def onLongs(n1: java.lang.Long, n2: java.lang.Long): Int = n1.compareTo(n2)
×
131
      override def onBigIntegers(n1: java.math.BigInteger, n2: java.math.BigInteger): Int = n1.compareTo(n2)
×
132
      override def onFloats(n1: java.lang.Float, n2: java.lang.Float): Int = n1.compareTo(n2)
×
133
      override def onDoubles(n1: java.lang.Double, n2: java.lang.Double): Int = n1.compareTo(n2)
×
134
      override def onBigDecimals(n1: java.math.BigDecimal, n2: java.math.BigDecimal): Int = n1.compareTo(n2)
×
135
    })(NumberTypesPromotionStrategy.ForMathOperation)
2✔
136
  }
137

138
  def greater(n1: Number, n2: Number): Boolean = compare(n1, n2) > 0
2✔
139
  def greaterOrEqual(n1: Number, n2: Number): Boolean = compare(n1, n2) >= 0
2✔
140
  def lesser(n1: Number, n2: Number): Boolean = compare(n1, n2) < 0
×
141
  def lesserOrEqual(n1: Number, n2: Number): Boolean = compare(n1, n2) <= 0
2✔
142
  def equal(n1: Number, n2: Number): Boolean = compare(n1, n2) == 0
×
143
  def notEqual(n1: Number, n2: Number): Boolean = compare(n1, n2) != 0
×
144

145
  private def promoteThenSum(n1: Number, n2: Number)(implicit promotionStrategy: ReturningSingleClassPromotionStrategy) = {
146
    withNotNullValues(n1, n2) {
6✔
147
      withValuesWithTheSameType(n1, n2)(new SameNumericTypeHandlerForPromotingMathOp {
148
        override def onInts(n1: java.lang.Integer, n2: java.lang.Integer): java.lang.Integer = n1 + n2
149
        override def onLongs(n1: java.lang.Long, n2: java.lang.Long): java.lang.Long = n1 + n2
150
        override def onBigIntegers(n1: java.math.BigInteger, n2: java.math.BigInteger): java.math.BigInteger = n1.add(n2)
151
        override def onFloats(n1: java.lang.Float, n2: java.lang.Float): java.lang.Float = n1 + n2
152
        override def onDoubles(n1: java.lang.Double, n2: java.lang.Double): java.lang.Double = n1 + n2
153
        override def onBigDecimals(n1: java.math.BigDecimal, n2: java.math.BigDecimal): java.math.BigDecimal = n1.add(n2)
154
      })
155
    }
156
  }
157

158
  protected def withNotNullValues(n1: Number, n2: Number)(f: => Number)
159
                                 (implicit promotionStrategy: ReturningSingleClassPromotionStrategy): Number = {
160
    if (n1 == null) {
6✔
161
      if (n2 == null) null else convertToPromotedType(n2)
4✔
162
    } else if (n2 == null) {
6✔
163
      convertToPromotedType(n1)
2✔
164
    } else {
165
      f
6✔
166
    }
167
  }
168

169
  protected def withValuesWithTheSameType[R](n1: Number, n2: Number)(handler: SameNumericTypeHandler[R])
170
                                            (implicit promotionStrategy: ReturningSingleClassPromotionStrategy): R = {
171
    val promotedClass = promotionStrategy.promoteClasses(n1.getClass, n2.getClass).klass
6✔
172
    if (promotedClass == classOf[java.lang.Byte]) {
6✔
173
      handler.onBytes(SpringNumberUtils.convertNumberToTargetClass(n1, classOf[java.lang.Byte]), SpringNumberUtils.convertNumberToTargetClass(n2, classOf[java.lang.Byte]))
×
174
    } else if (promotedClass == classOf[java.lang.Short]) {
6✔
175
      handler.onShorts(SpringNumberUtils.convertNumberToTargetClass(n1, classOf[java.lang.Short]), SpringNumberUtils.convertNumberToTargetClass(n2, classOf[java.lang.Short]))
×
176
    } else if (promotedClass == classOf[java.lang.Integer]) {
6✔
177
      handler.onInts(SpringNumberUtils.convertNumberToTargetClass(n1, classOf[java.lang.Integer]), SpringNumberUtils.convertNumberToTargetClass(n2, classOf[java.lang.Integer]))
6✔
178
    } else if (promotedClass == classOf[java.lang.Long]) {
6✔
179
      handler.onLongs(SpringNumberUtils.convertNumberToTargetClass(n1, classOf[java.lang.Long]), SpringNumberUtils.convertNumberToTargetClass(n2, classOf[java.lang.Long]))
4✔
180
    } else if (promotedClass == classOf[java.math.BigInteger]) {
4✔
181
      handler.onBigIntegers(SpringNumberUtils.convertNumberToTargetClass(n1, classOf[java.math.BigInteger]), SpringNumberUtils.convertNumberToTargetClass(n2, classOf[java.math.BigInteger]))
×
182
    } else if (promotedClass == classOf[java.lang.Float]) {
4✔
183
      handler.onFloats(SpringNumberUtils.convertNumberToTargetClass(n1, classOf[java.lang.Float]), SpringNumberUtils.convertNumberToTargetClass(n2, classOf[java.lang.Float]))
2✔
184
    } else if (promotedClass == classOf[java.lang.Double]) {
4✔
185
      handler.onDoubles(SpringNumberUtils.convertNumberToTargetClass(n1, classOf[java.lang.Double]), SpringNumberUtils.convertNumberToTargetClass(n2, classOf[java.lang.Double]))
4✔
186
    } else if (promotedClass == classOf[java.math.BigDecimal]) {
2✔
187
      handler.onBigDecimals(SpringNumberUtils.convertNumberToTargetClass(n1, classOf[java.math.BigDecimal]), SpringNumberUtils.convertNumberToTargetClass(n2, classOf[java.math.BigDecimal]))
2✔
188
    } else {
189
      throw new IllegalStateException(s"Unexpected result of number promotion: $promotedClass for types: ${n1.getClass} and ${n2.getClass}")
×
190
    }
191
  }
192

193
  private def convertToPromotedType(n: Number)(implicit promotionStrategy: ReturningSingleClassPromotionStrategy): Number = {
194
    // In some cases type can be promoted to other class e.g. Byte is promoted to Int for sum
195
    val promotedClass = promotionStrategy.promoteClasses(n.getClass, n.getClass).klass.asInstanceOf[Class[_ <: Number]]
4✔
196
    SpringNumberUtils.convertNumberToTargetClass(n, promotedClass)
4✔
197
  }
198

199
  protected trait SameNumericTypeHandler[R] {
200
    def onBytes(n1: java.lang.Byte, n2: java.lang.Byte): R
201
    def onShorts(n1: java.lang.Short, n2: java.lang.Short): R
202
    def onInts(n1: java.lang.Integer, n2: java.lang.Integer): R
203
    def onLongs(n1: java.lang.Long, n2: java.lang.Long): R
204
    def onBigIntegers(n1: java.math.BigInteger, n2: java.math.BigInteger): R
205
    def onFloats(n1: java.lang.Float, n2: java.lang.Float): R
206
    def onDoubles(n1: java.lang.Double, n2: java.lang.Double): R
207
    def onBigDecimals(n1: java.math.BigDecimal, n2: java.math.BigDecimal): R
208
  }
209

210
  protected trait SameNumericTypeHandlerReturningNumber extends SameNumericTypeHandler[Number] {
211
    override def onBytes(n1: lang.Byte, n2: lang.Byte): java.lang.Byte
212
    override def onShorts(n1: lang.Short, n2: lang.Short): java.lang.Short
213
    override def onInts(n1: java.lang.Integer, n2: java.lang.Integer): java.lang.Integer
214
    override def onLongs(n1: java.lang.Long, n2: java.lang.Long): java.lang.Long
215
    override def onBigIntegers(n1: java.math.BigInteger, n2: java.math.BigInteger): java.math.BigInteger
216
    override def onFloats(n1: java.lang.Float, n2: java.lang.Float): java.lang.Float
217
    override def onDoubles(n1: java.lang.Double, n2: java.lang.Double): java.lang.Double
218
    override def onBigDecimals(n1: java.math.BigDecimal, n2: java.math.BigDecimal): java.math.BigDecimal
219
  }
220

221
  protected trait SameNumericTypeHandlerForPromotingMathOp extends SameNumericTypeHandlerReturningNumber {
222
    override final def onBytes(n1: java.lang.Byte, n2: java.lang.Byte): Nothing =
223
      throw new IllegalStateException("Bytes should be promoted to Ints before operator")
×
224
    override final def onShorts(n1: java.lang.Short, n2: java.lang.Short): Nothing =
225
      throw new IllegalStateException("Bytes should be promoted to Ints before operator")
×
226

227
  }
228
}
229

230
object MathUtils extends MathUtils
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc