Skip to content

Commit

Permalink
Close #83 - [core] Add NegBigDecimal, NonNegBigDecimal, PosBigDecimal…
Browse files Browse the repository at this point in the history
… and NonPosBigDecimal to numeric package
  • Loading branch information
kevin-lee committed Dec 9, 2023
1 parent 7be84ee commit 10f3e18
Show file tree
Hide file tree
Showing 3 changed files with 995 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ object numericTools {

val BigInt0: BigInt = BigInt(0)

val BigDecimal0: BigDecimal = BigDecimal(0)

def isNegativeBigInt(value: Expr[BigInt])(using Quotes): Expr[Boolean] = {
import quotes.reflect.*

Expand Down Expand Up @@ -125,4 +127,171 @@ object numericTools {
}
}

// format: off
def isNegativeBigDecimal(value: Expr[BigDecimal])(using Quotes): Expr[Boolean] = {
import quotes.reflect.*

value.asTerm match {
case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(StringConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) < BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(StringConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) < BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(IntConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) < BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(IntConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) < BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(LongConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) < BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(LongConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) < BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Apply(Ident("float2double"), List(Literal(FloatConstant(bigDecimalValue)))))))) =>
Expr(BigDecimal(bigDecimalValue) < BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Apply(Ident("float2double"), List(Inlined(_, _, Literal(FloatConstant(bigDecimalValue))))))))) =>
Expr(BigDecimal(bigDecimalValue) < BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(DoubleConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) < BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(DoubleConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) < BigDecimal0)

// $COVERAGE-OFF$
case x =>
println(x)
Expr(false)
// $COVERAGE-ON$
}
}

def isNonNegativeBigDecimal(value: Expr[BigDecimal])(using Quotes): Expr[Boolean] = {
import quotes.reflect.*

value.asTerm match {
case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(StringConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) >= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(StringConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) >= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(IntConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) >= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(IntConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) >= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(LongConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) >= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(LongConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) >= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Apply(Ident("float2double"), List(Literal(FloatConstant(bigDecimalValue)))))))) =>
Expr(BigDecimal(bigDecimalValue) >= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Apply(Ident("float2double"), List(Inlined(_, _, Literal(FloatConstant(bigDecimalValue))))))))) =>
Expr(BigDecimal(bigDecimalValue) >= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(DoubleConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) >= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(DoubleConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) >= BigDecimal0)

// $COVERAGE-OFF$
case _ =>
Expr(false)
// $COVERAGE-ON$
}
}

def isPositiveBigDecimal(value: Expr[BigDecimal])(using Quotes): Expr[Boolean] = {
import quotes.reflect.*

value.asTerm match {
case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(StringConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) > BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(StringConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) > BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(IntConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) > BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(IntConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) > BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(LongConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) > BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(LongConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) > BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Apply(Ident("float2double"), List(Literal(FloatConstant(bigDecimalValue)))))))) =>
Expr(BigDecimal(bigDecimalValue) > BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Apply(Ident("float2double"), List(Inlined(_, _, Literal(FloatConstant(bigDecimalValue))))))))) =>
Expr(BigDecimal(bigDecimalValue) > BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(DoubleConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) > BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(DoubleConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) > BigDecimal0)

// $COVERAGE-OFF$
case _ =>
Expr(false)
// $COVERAGE-ON$
}
}

def isNonPositiveBigDecimal(value: Expr[BigDecimal])(using Quotes): Expr[Boolean] = {
import quotes.reflect.*

value.asTerm match {
case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(StringConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) <= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(StringConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) <= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(IntConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) <= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(IntConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) <= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(LongConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) <= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(LongConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) <= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Apply(Ident("float2double"), List(Literal(FloatConstant(bigDecimalValue)))))))) =>
Expr(BigDecimal(bigDecimalValue) <= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Apply(Ident("float2double"), List(Inlined(_, _, Literal(FloatConstant(bigDecimalValue))))))))) =>
Expr(BigDecimal(bigDecimalValue) <= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Literal(DoubleConstant(bigDecimalValue)))))) =>
Expr(BigDecimal(bigDecimalValue) <= BigDecimal0)

case Inlined(_, _, Inlined(_, _, Apply(Select(Ident("BigDecimal"), _), List(Inlined(_, _, Literal(DoubleConstant(bigDecimalValue))))))) =>
Expr(BigDecimal(bigDecimalValue) <= BigDecimal0)

// $COVERAGE-OFF$
case _ =>
Expr(false)
// $COVERAGE-ON$
}
}
// format: on

}
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ trait numeric {

val BigInt0: BigInt = numericTools.BigInt0

val BigDecimal0: BigDecimal = numericTools.BigDecimal0

type NegBigInt = NegBigInt.Type
@SuppressWarnings(Array("org.wartremover.warts.Overloading"))
object NegBigInt extends InlinedNumeric[BigInt] {
Expand All @@ -232,7 +234,7 @@ trait numeric {

inline def apply(inline a: Int): Type = apply(BigInt(a))

inline def apply(a: Long): Type = apply(BigInt(a))
inline def apply(inline a: Long): Type = apply(BigInt(a))

inline def apply(inline a: String): Type = apply(BigInt(a))
}
Expand Down Expand Up @@ -285,5 +287,85 @@ trait numeric {
inline def apply(inline a: String): Type = apply(BigInt(a))
}

type NegBigDecimal = NegBigDecimal.Type
@SuppressWarnings(Array("org.wartremover.warts.Overloading"))
object NegBigDecimal extends InlinedNumeric[BigDecimal] {
override def invalidReason(a: BigDecimal): String = expectedMessage("a negative BigDecimal")

override def predicate(a: BigDecimal): Boolean = a < BigDecimal0

override inline def inlinedPredicate(inline a: BigDecimal): Boolean = ${ numericTools.isNegativeBigDecimal('a) }

inline def apply(inline a: Int): Type = apply(BigDecimal(a))

inline def apply(inline a: Long): Type = apply(BigDecimal(a))

inline def apply(inline a: Float): Type = apply(BigDecimal(a))

inline def apply(inline a: Double): Type = apply(BigDecimal(a))

inline def apply(inline a: String): Type = apply(BigDecimal(a))
}

type NonNegBigDecimal = NonNegBigDecimal.Type
@SuppressWarnings(Array("org.wartremover.warts.Overloading"))
object NonNegBigDecimal extends InlinedNumeric[BigDecimal] {
override def invalidReason(a: BigDecimal): String = expectedMessage("a non-negative BigDecimal")

override def predicate(a: BigDecimal): Boolean = a >= BigDecimal0

override inline def inlinedPredicate(inline a: BigDecimal): Boolean = ${ numericTools.isNonNegativeBigDecimal('a) }

inline def apply(inline a: Int): Type = apply(BigDecimal(a))

inline def apply(inline a: Long): Type = apply(BigDecimal(a))

inline def apply(inline a: Float): Type = apply(BigDecimal(a))

inline def apply(inline a: Double): Type = apply(BigDecimal(a))

inline def apply(inline a: String): Type = apply(BigDecimal(a))
}

type PosBigDecimal = PosBigDecimal.Type
@SuppressWarnings(Array("org.wartremover.warts.Overloading"))
object PosBigDecimal extends InlinedNumeric[BigDecimal] {
override def invalidReason(a: BigDecimal): String = expectedMessage("a positive BigDecimal")

override def predicate(a: BigDecimal): Boolean = a > BigDecimal0

override inline def inlinedPredicate(inline a: BigDecimal): Boolean = ${ numericTools.isPositiveBigDecimal('a) }

inline def apply(inline a: Int): Type = apply(BigDecimal(a))

inline def apply(inline a: Long): Type = apply(BigDecimal(a))

inline def apply(inline a: Float): Type = apply(BigDecimal(a))

inline def apply(inline a: Double): Type = apply(BigDecimal(a))

inline def apply(inline a: String): Type = apply(BigDecimal(a))
}

type NonPosBigDecimal = NonPosBigDecimal.Type
@SuppressWarnings(Array("org.wartremover.warts.Overloading"))
object NonPosBigDecimal extends InlinedNumeric[BigDecimal] {
override def invalidReason(a: BigDecimal): String = expectedMessage("a non-positive BigDecimal")

override def predicate(a: BigDecimal): Boolean = a <= BigDecimal0

override inline def inlinedPredicate(inline a: BigDecimal): Boolean = ${ numericTools.isNonPositiveBigDecimal('a) }

inline def apply(inline a: Int): Type = apply(BigDecimal(a))

inline def apply(inline a: Long): Type = apply(BigDecimal(a))

inline def apply(inline a: Float): Type = apply(BigDecimal(a))

inline def apply(inline a: Double): Type = apply(BigDecimal(a))

inline def apply(inline a: String): Type = apply(BigDecimal(a))
}

}
object numeric extends numeric
Loading

0 comments on commit 10f3e18

Please sign in to comment.