2.8 Subdomains Again

A subdomain S of a domain D is a domain consisting of

  1. those elements of D that satisfy some predicate (that is, a test that returns true or false) and
  2. a subset of the operations of D.

Every domain is a subdomain of itself, trivially satisfying the membership test: true.

Currently, there are only two system-defined subdomains in FriCAS that receive substantial use. PositiveInteger and NonNegativeInteger are subdomains of Integer. An element x of NonNegativeInteger is an integer that is greater than or equal to zero, that is, satisfies x>=0. An element x of PositiveInteger is a nonnegative integer that is, in fact, greater than zero, that is, satisfies x>0. Not all operations from Integer are available for these subdomains. For example, negation and subtraction are not provided since the subdomains are not closed under those operations. When you use an integer in an expression, FriCAS assigns to it the type that is the most specific subdomain whose predicate is satisfied.

This is a positive integer.


Type: PositiveInteger

This is a nonnegative integer.


Type: NonNegativeInteger

This is neither of the above.


Type: Integer

Furthermore, unless you are assigning an integer to a declared variable or using a conversion, any integer result has as type the most specific subdomain.

(-2) - (-3)

Type: PositiveInteger

0 :: Integer

Type: Integer

x : NonNegativeInteger := 5

Type: NonNegativeInteger

When necessary, FriCAS converts an integer object into one belonging to a less specific subdomain. For example, in 3-2, the arguments to “-” are both elements of PositiveInteger, but this type does not provide a subtraction operation. Neither does NonNegativeInteger, so 3 and 2 are viewed as elements of Integer, where their difference can be calculated. The result is 1, which FriCAS then automatically assigns the type PositiveInteger.

Certain operations are very sensitive to the subdomains to which their arguments belong. This is an element of PositiveInteger.

2 ^ 2

Type: PositiveInteger

This is an element of Fraction Integer.

2 ^ (-2)

Type: Fraction Integer

It makes sense then that this is a list of elements of PositiveInteger.

[10^i for i in 2..5]
\[\left[ {100}, \: {1000}, \: {10000}, \: {100000} \right]\]

Type: List PositiveInteger

What should the type of [10^(i-1) for i in 2..5] be? On one hand, i-1 is always an integer greater than zero as i ranges from 2 to 5 and so 10^i is also always a positive integer. On the other, i-1 is a very simple function of i. FriCAS does not try to analyze every such function over the index’s range of values to determine whether it is always positive or nowhere negative. For an arbitrary FriCAS function, this analysis is not possible.

So, to be consistent no such analysis is done and we get this.

[10^(i-1) for i in 2..5]
\[\left[ {10}, \: {100}, \: {1000}, \: {10000} \right]\]

Type: List Fraction Integer

To get a list of elements of PositiveInteger instead, you have two choices. You can use a conversion.

[10^((i-1) :: PI) for i in 2..5]
Compiling function G82696 with type Integer -> Boolean
Compiling function G82708 with type NonNegativeInteger -> Boolean
\[\left[ {10}, \: {100}, \: {1000}, \: {10000} \right]\]

Type: List PositiveInteger

Or you can use pretend.

[10^((i-1) pretend PI) for i in 2..5]
\[\left[ {10}, \: {100}, \: {1000}, \: {10000} \right]\]

Type: List PositiveInteger

The operation pretend is used to defeat the FriCAS type system. The expression object pretend D means make a new object (without copying) of type D from object. If object were an integer and you told FriCAS to pretend it was a list, you would probably see a message about a fatal error being caught and memory possibly being damaged. Lists do not have the same internal representation as integers!

You use pretend at your peril.

Use pretend with great care! FriCAS trusts you that the value is of the specified type.

(2/3) pretend Complex Integer
\[2+{3 \ i}\]

Type: Complex Integer