From 3e957828fc38cf89b557f6a7fe006607ff653c29 Mon Sep 17 00:00:00 2001 From: Attila Mihaly <60483498+AttilaMihaly@users.noreply.github.com> Date: Wed, 18 Nov 2020 12:17:51 -0500 Subject: [PATCH] Add missing sdk functions (#69) * Added functions to cover reference model. #65 * More Basics utilities. #65 * Fixed compile and test errors. #65 * Added some missing functions. #65 --- morphir/sdk/core/src/morphir/sdk/Basics.scala | 32 ++++++++++++++- morphir/sdk/core/src/morphir/sdk/List.scala | 40 +++++++++++-------- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/morphir/sdk/core/src/morphir/sdk/Basics.scala b/morphir/sdk/core/src/morphir/sdk/Basics.scala index 31ad6d3b..04256d38 100644 --- a/morphir/sdk/core/src/morphir/sdk/Basics.scala +++ b/morphir/sdk/core/src/morphir/sdk/Basics.scala @@ -18,7 +18,12 @@ package morphir.sdk object Basics { + // Bool type Bool = scala.Boolean + @inline def not(a: Bool): Bool = !a + @inline def and(a: Bool, b: Bool): Bool = a && b + @inline def or(a: Bool, b: Bool): Bool = a || b + @inline def xor(a: Bool, b: Bool): Bool = (a && !b) || (!a && b) // Equality @inline def equal[A](a: A)(b: A): Bool = a == b @@ -35,15 +40,31 @@ object Basics { def min[A: Ordering](a: A)(b: A): A = if (lessThan(a)(b)) a else b def max[A: Ordering](a: A)(b: A): A = if (greaterThan(a)(b)) a else b - // Int + // Int construction type Int = scala.Long def Int(v: scala.Long): Int = v + // Int functions + @inline def lessThan(a: Int)(b: Int): Bool = a < b + @inline def lessThanOrEqual(a: Int)(b: Int): Bool = a <= b + @inline def greaterThan(a: Int)(b: Int): Bool = a > b + @inline def greaterThanOrEqual(a: Int)(b: Int): Bool = a >= b + @inline def min(a: Int)(b: Int): Int = a min b + @inline def max(a: Int)(b: Int): Float = a max b @inline def add(a: Int)(b: Int): Int = a + b @inline def subtract(a: Int)(b: Int): Int = a - b @inline def multiply(a: Int)(b: Int): Int = a * b @inline def integerDivide(a: Int)(b: Int): Int = a / b @inline def power(a: Int)(b: Int): Int = a ^ b + @inline def modBy(a: Int)(b: Int): Int = Math.floorMod(a, b) + @inline def remainderBy(a: Int)(b: Int): Int = a % b + @inline def negate(a: Int): Int = -a + @inline def abs(a: Int): Int = Math.abs(a) + @inline def clamp(min: Int)(max: Int)(a: Int): Int = { + if (a < min) min + else if (a > max) max + else a + } // Float construction type Float = scala.Double @@ -66,6 +87,15 @@ object Basics { @inline def floor(a: Float): Int = a.floor.round @inline def ceiling(a: Float): Int = a.ceil.round @inline def truncate(a: Float): Int = if (a >= 0) floor(a) else -floor(-a) + @inline def negate(a: Float): Float = -a + @inline def abs(a: Float): Float = Math.abs(a) + @inline def clamp(min: Float)(max: Float)(a: Float): Float = { + if (a < min) min + else if (a > max) max + else a + } + @inline def isNaN(a: Float): Bool = a.isNaN + @inline def isInfinite(a: Float): Bool = a.isInfinite // Utilities @inline def identity[A](a: A): A = scala.Predef.identity(a) diff --git a/morphir/sdk/core/src/morphir/sdk/List.scala b/morphir/sdk/core/src/morphir/sdk/List.scala index f4849435..c24d4921 100644 --- a/morphir/sdk/core/src/morphir/sdk/List.scala +++ b/morphir/sdk/core/src/morphir/sdk/List.scala @@ -12,12 +12,11 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -*/ - + */ package morphir.sdk -import morphir.sdk.Maybe.{ Just, Maybe } +import morphir.sdk.Maybe.{Just, Maybe} object List { type List[+A] = scala.List[A] @@ -74,45 +73,45 @@ object List { lst.take(xs.length - 1).flatMap(x => List(x, elem)) ++ List(xs.last) } - @inline def length[A](xs: List[A]): Int = xs.length + @inline def length[A](xs: List[A]): Int = xs.length @inline def singleton[A](item: A): List[A] = scala.List(item) @inline def map[A, B](mapping: A => B)(list: List[A]): List[B] = list.map(mapping) /** - * Combine two lists, combining them with the given function. If one list is longer, the extra elements are dropped. - * @param mapping a mapping function - * @param xs the first list - * @param ys the second list - * @tparam A the type of the first list - * @tparam B the type of the second list - * @tparam R the type of the resulting list - * @return a list containing the combined elements of list1 and list2 using the mapping function. - */ + * Combine two lists, combining them with the given function. If one list is longer, the extra elements are dropped. + * @param mapping a mapping function + * @param xs the first list + * @param ys the second list + * @tparam A the type of the first list + * @tparam B the type of the second list + * @tparam R the type of the resulting list + * @return a list containing the combined elements of list1 and list2 using the mapping function. + */ def map2[A, B, R]( - mapping: A => B => R + mapping: A => B => R )(xs: List[A])(ys: List[B]): List[R] = xs.zip(ys).map { case (a, b) => mapping(a)(b) } def map3[X, Y, Z, R]( - mapping: X => Y => Z => R + mapping: X => Y => Z => R )(xs: List[X])(ys: List[Y])(zs: List[Z]): List[R] = xs.zip(ys).zip(zs).map { case ((x, y), z) => mapping(x)(y)(z) } def map4[A, B, C, D, R]( - mapping: A => B => C => D => R + mapping: A => B => C => D => R )(as: List[A])(bs: List[B])(cs: List[C])(ds: List[D]): List[R] = as.zip(bs).zip(cs).zip(ds).map { case (((a, b), c), d) => mapping(a)(b)(c)(d) } def map5[A, B, C, D, E, R]( - mapping: A => B => C => D => E => R + mapping: A => B => C => D => E => R )(as: List[A])(bs: List[B])(cs: List[C])(ds: List[D])(es: List[E]): List[R] = as.zip(bs) .zip(cs) @@ -145,4 +144,11 @@ object List { @inline def unzip[A, B](xs: List[(A, B)]): (List[A], List[B]) = xs.unzip + + @inline def minimum[A: Ordering](list: List[A]): Maybe[A] = + if (list.isEmpty) Maybe.Nothing else Maybe.Just(list.min) + @inline def maximum[A: Ordering](list: List[A]): Maybe[A] = + if (list.isEmpty) Maybe.Nothing else Maybe.Just(list.max) + @inline def sum[A: Numeric](list: List[A]): A = list.sum + @inline def product[A: Numeric](list: List[A]): A = list.product }