Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 46 additions & 12 deletions core/src/main/scala/latis/model/DataTypeAlgebra.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ trait DataTypeAlgebra { dataType: DataType =>
}
go(dataType)
}

/** Returns Scalars in the model that are not an Index. */
def nonIndexScalars: List[Scalar] =
getScalars.filterNot(_.isInstanceOf[Index])
Expand All @@ -59,22 +59,56 @@ trait DataTypeAlgebra { dataType: DataType =>
case Function(d, r) => Function.from(id, d, r).fold(throw _, identity)
}

/**
* Returns the top level domain variables without flattening.
*
* Element of an anonymous outer domain (placeholder) Tuple will be extracted.
* Note that Scalars and Tuples are the range of a 0-arity Function.
*/
def domainVariables: List[DataType] = dataType match {
case Function(domain, _) => domain match {
case t: Tuple => if (t.id.isEmpty) t.elements else List(t)
case v => List(v)
}
case _ => List.empty
}

/**
* Returns the top level range variables without flattening.
*
* Element of an anonymous outer range (placeholder) Tuple will be extracted.
* Note that Scalars and Tuples are the range of a 0-arity Function.
*/
def rangeVariables: List[DataType] = dataType match {
case Function(_, range) => range match {
case t: Tuple => if (t.id.isEmpty) t.elements else List(t)
case v => List(v)
}
case t: Tuple => if (t.id.isEmpty) t.elements else List(t)
case s: Scalar => List(s)
}

/**
* Returns the arity of this DataType.
*
* For a Function, this is the number of top level types (non-flattened)
* in the domain. For Scalar and Tuple, there is no domain so the arity is 0.
* For a Function, arity is the number of top level variables in the
* domain. Other than an outer anonymous Tuple which is used
* only to contain multiple domain variables, a Tuple will count as a single
* variable as opposed to counting the variables nested within it
* (as opposed to `dimension`). For a Scalar or Tuple, there is no
* domain so the arity is 0. This is akin to the number of arguments
* in a function call.
*/
def arity: Int = dataType.domainVariables.size

/**
* Returns the number of dimensions covered by this DataType.
*
* Beware that this is not the same as dimensionality since a nested tuple
* counts as one towards arity.
* The dimension is the number of Scalars in the domain of a Function.
* A lone Tuple or Scalar has zero dimensions.
*/
def arity: Int = dataType match {
case Function(domain, _) =>
domain match {
case _: Scalar => 1
case t: Tuple => t.elements.length
case _: Function => ??? //bug, Function not allowed in domain
}
def dimension: Int = dataType match {
case Function(domain, _) => domain.getScalars.size
case _ => 0
}

Expand Down
106 changes: 88 additions & 18 deletions core/src/test/scala/latis/model/DataTypeSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,35 @@ class DataTypeSuite extends FunSuite {

private lazy val i = Index()
private lazy val x = Scalar(id"x", IntValueType)
//private lazy val y = Scalar(id"y", IntValueType)
private lazy val z = Scalar(id"z", IntValueType)
private lazy val a = Scalar(id"a", IntValueType)
private lazy val b = Scalar(id"b", DoubleValueType)
private lazy val c = Scalar(id"c", StringValueType)
private lazy val namedTup = Tuple.fromElements(id"t", a, b) // t: (a, b)
private lazy val namedTup = Tuple.fromElements(id"t", a, b) // t: (a, b)
.fold(fail("failed to construct tuple", _), identity)
//private lazy val anonTup = Tuple.fromElements(a, b).value // (a, b)
private lazy val nestedTup = Tuple.fromElements(namedTup, c) // (t: (a, b), c)
private lazy val anonTup = Tuple.fromElements(a, b) // (a, b)
.fold(fail("failed to construct tuple", _), identity)
private lazy val f = Function.from(id"f", x, a) // f: x -> a
private lazy val nestedTup = Tuple.fromElements(namedTup, c) // (t: (a, b), c)
.fold(fail("failed to construct tuple", _), identity)
private lazy val f = Function.from(id"f", x, a) // f: x -> a
.fold(fail("failed to construct function", _), identity)
private lazy val fWithTup = Function.from(id"f", x, namedTup) // f: x -> t: (a, b)
.fold(fail("failed to construct function", _), identity)
private lazy val fWithTup = Function.from(id"f", x, namedTup) // f: x -> t: (a, b)
private lazy val fWithAnonTup = Function.from(id"f", x, anonTup) // f: x -> (a, b)
.fold(fail("failed to construct function", _), identity)
private lazy val tupWithF = Tuple.fromElements(a, fWithTup) // (a, f: x -> t: (a, b))
private lazy val fWithNestedTup = Function.from(id"f", x, nestedTup) // f: x -> (t: (a, b), c)
.fold(fail("failed to construct function", _), identity)
private lazy val tupWithF = Tuple.fromElements(a, fWithTup) // (a, f: x -> t: (a, b))
.fold(fail("failed to construct tuple", _), identity)
private lazy val nestedF = Function.from(id"g", z, f) // g: z -> f: x -> a
private lazy val nestedF = Function.from(id"g", z, f) // g: z -> f: x -> a
.fold(fail("failed to construct function", _), identity)
private lazy val nestedFInTup = Function.from(id"g", i, tupWithF) // g: _i -> (a, f: x -> t: (a, b))
.fold(fail("failed to construct function", _), identity)
private lazy val nestedFInTup = Function.from(id"g", i, tupWithF) // g: _i -> (a, f: x -> t: (a, b))
private lazy val fWithAnonTupDomain = Function.from(anonTup, z) // (a, b) -> z
.fold(fail("failed to construct function", _), identity)
private lazy val fWithNamedTupDomain = Function.from(namedTup, z) // t: (a, b) -> z
.fold(fail("failed to construct function", _), identity)
private lazy val fWithNestedTupDomain = Function.from(nestedTup, z) // (t: (a, b), c) -> z
.fold(fail("failed to construct function", _), identity)

test("to string") {
Expand Down Expand Up @@ -105,11 +115,11 @@ class DataTypeSuite extends FunSuite {
}

test("path to scalar in nested function") {
assert(nestedF.findPath(id"a").contains(List(RangePosition(0),RangePosition(0))))
assert(nestedF.findPath(id"a").contains(List(RangePosition(0), RangePosition(0))))
}

test("path to scalar in nested function in tuple") {
assert(nestedFInTup.findPath(id"b").contains(List(RangePosition(1),RangePosition(1))))
assert(nestedFInTup.findPath(id"b").contains(List(RangePosition(1), RangePosition(1))))
}

//---- fillData ----//
Expand All @@ -134,7 +144,7 @@ class DataTypeSuite extends FunSuite {
}

test("not exists") {
assert(! f.exists(_.isInstanceOf[Tuple]))
assert(!f.exists(_.isInstanceOf[Tuple]))
}

test("self exists") {
Expand All @@ -144,40 +154,100 @@ class DataTypeSuite extends FunSuite {
//---- simply nested function ---//

test("scalar is not simply nested") {
assert(! x.isSimplyNested)
assert(!x.isSimplyNested)
}

test("tuple is not simply nested") {
assert(! namedTup.isSimplyNested)
assert(!namedTup.isSimplyNested)
}

test("nested function is simply nested") {
assert(nestedF.isSimplyNested)
}

test("complex nested function is not simply nested") {
assert(! nestedFInTup.isSimplyNested)
assert(!nestedFInTup.isSimplyNested)
}

//---- complexity ----//

test("scalar is not complex") {
assert(! x.isComplex)
assert(!x.isComplex)
}

test("nested tuple is not complex") {
assert(! nestedTup.isComplex)
assert(!nestedTup.isComplex)
}

test("tuple with function is complex") {
assert(tupWithF.isComplex)
}

test("simply nested function is not complex") {
assert(! nestedF.isComplex)
assert(!nestedF.isComplex)
}

test("complex nested function is complex") {
assert(nestedFInTup.isComplex)
}

//---- dimension, and arity ----//

// Note that `arity` effectively tests `domainVariables`

// f: x -> a
test("scalar domain") {
assertEquals(f.arity, 1)
assertEquals(f.dimension, 1)
}

// (a, b) -> z
test("anon tuple domain") {
assertEquals(fWithAnonTupDomain.arity, 2)
assertEquals(fWithAnonTupDomain.dimension, 2)
}

// t: (a, b) -> z
test("named tuple domain") {
assertEquals(fWithNamedTupDomain.arity, 1)
assertEquals(fWithNamedTupDomain.dimension, 2)
}

// (t: (a, b), c) -> z
test("nested tuple domain list") {
assertEquals(fWithNestedTupDomain.arity, 2)
assertEquals(fWithNestedTupDomain.dimension, 3)
}

test("non Function") {
assertEquals(x.arity, 0)
assertEquals(x.dimension, 0)
}

//---- Range variables ----//

// f: x -> a
test("scalar range list") {
assertEquals(f.rangeVariables.size, 1)
}

// f: x -> (a, b)
test("anon tuple range list") {
assertEquals(fWithAnonTup.rangeVariables.size, 2)
}

// f: x -> t: (a, b)
test("named tuple range list") {
assertEquals(fWithTup.rangeVariables.size, 1)
}

// f: x -> (t: (a, b), c)
test("nested tuple range list") {
assertEquals(fWithNestedTup.rangeVariables.size, 2)
}

// g: _i -> (a, f: x -> t: (a, b))
test("nested function range list") {
assertEquals(nestedFInTup.rangeVariables.size, 2)
}
}
Loading