Language English (original text) Français

# Arithmetic and booleans

## Specifying numbers

Here are the Pliant notations for 100 in decimal, hexadecimal and binary encoding:

100
64h
1100100b
100n

The last line is also 100 but with type Intn. See 'Unlimited integers' section bellow.

## Basic arithmetic

The four classical arithmetic operators are noted + - * and \ or / in Pliant.
The classical priority rules are applied, so that:

console 3+4*2 eol

will display 11, not 14.

'\' means integer division, '/' means floting point division:

console 7\3 eol
console 7/3 eol

'%' is the remaining operator:

console 7%3 eol

'^' is the power operator:

console 7^3 eol

Basic arithmetic on integers is implemented in /pliant/graphic/language/basic/arithmetric.c

## Compact notations

var Int i := 3
+= 2

is the same as

var Int i := 3
i := i+2

Of course, we also have '-=' '*=' '\=' '/=' '%=' and '^=' operators.

For advanced users, please notice that these operators can be purely syntactical. I mean, if you define '+' operator for a new data type, then '+=' will work automatically though you may define it to provide more optimal implementation of this special case.

## Exchanging

While I'm talking about assigning (I have to move all this to a better place since it's not related to arithmetic), swap instruction can be used to exchange values:

var Array:Int i j
swap i j

The key advantage of 'swap' is that it's efficient because it only exchanges the scalar part of the data (in this example, the elements in the array will not be moved).
The big warning is: swap does not handle back pointers, so if the data has back pointers, it will silently be corrupted. A back pointer would be a pointer from a part of the data allocated somewhere else in the memory to the head of the data.
At some point, I should add a flag to enable data types to specify that they have back pointers, and prevent swap to work on them. Anyway, I have doubts any such type to exist in the all current Pliant tree, so it's not a top priority.

In other words, 'swap i j' is a more efficient equivalent to the following code:

var Pointer:Type t :> typeof i
check t=typeof:j
var Address b := memory_allocate t:size null
memory_free b

## Bits operators

Pliant provides bit to bit logical operations:

var Int i := 3
i := i .or. 10
i := i .and. 6
i := .not. i
console i eol

## Overflow

The following program will overflow, so display an unexpected result:

function fact x -> f
arg Int x f
f := shunt x=0 1 x*(fact x-1)
console fact:100 eol

If the program is run at debugging level 1, the overflow will happen silently, so the result will just be wrong. You can test it through copying the small program in a /pliant/test/fact.pli file, then issue the following command at the prompt (I mean use the:

pliant module /test/fact.pli

Now, if you switch from the default debugging level 1, to the stricter but much slower debugging level 2 through the following command:

pliant debug 2 module /test/fact.pli

then instead of silently computing and displaying the wrong result, Pliant will report an overflow error message.

Please notice that before starting to test Pliant programs at debugging level 2, you might have to type the following command to precompile Pliant core at debugging level 2:

pliant reset debug 2 'precompile /binary/default.dump module /pliant/install/precompile.pli'

Should you be aware of potential arithmetic overflow and assume it (it is a wanted or harmless feature in some algorithms), then you can use the side dotted arithmetic operators. The following program will silently overflow even when run at debugging level 2:

function fact x -> f
arg Int x f
f := shunt x=0 1 x.*.(fact x-1)
console fact:100 eol

Of course, we also have '.+.' and '.-.'

## Unlimited integers

Now, you can avoid the overflow issue through using the slower but unrestricted Intn data type instead of Int

function fact x -> f
arg Intn x f
f := shunt=0 1 x*(fact x-1)
console fact:100 eol

## Unsigned and fixed size integers

The size of a Pliant 'Int' on a 32 bits processor is 32 bits, and on a 64 bits process it is 64 bits as opposed to C.

Unsigned integers are:

var uInt i

Fixed size integers are:

var Int8 i
var Int16 i
var Int32 i
var Int64 i

var uInt8 i
var uInt16 i
var uInt32 i
var uInt64 i

The following data types are specifically high indian and low indian encoded:

var uInt_hi i
var uInt16_hi i
var uInt32_hi i
var uInt_li i
var uInt16_li i
var uInt32_li i

Please notice that several types are missing. I mean first 'uInt64_hi' and 'uInt64_li', then the all 'Int_hi' 'Int16_hi' 'Int32_hi' 'Int64_hi' and 'Int_li' 'Int16_li' 'Int32_li' 'Int64_li'. Should they be of any use at some point, extending the code in /pliant/language/type/number/int_indian.pli would be fairly straightforward.

## Floating point

Floating point data types are:

var Float f
var Float32 f
var Float64 f

Please notice that Float and Float64 are just the same.

Floating point constants can be provided as:

13.0
1.4e6

Transcendental functions:

module "/pliant/math/functions.pli"
var Float f g p
g := pi
g := sin f # sin pi/2 = 1
g := cos f
g := tan f
g := asin f
g := acos f
g := atan f
g := exp f # exp 1 = 2.71...
g := log f
g := pow f p

## Undefined value

Data type 'Int' has an undefined value:

var Int i := undefined

Also the undefined value is just a symbolic one, not an effective one. In the following sample:

var Int i := undefined
console i eol
var Int j := i+1
console j eol

The value of 'j' is not 'undefined' as common sense would expect:

?
-2147483647

More precisely, on a 32 bits system, undefined value is just the value -2^31.

On the other hand, when handled as a floatting point data, undefined value is effective:

var Float i := undefined
console i eol
var Float j := i+1
console j eol

The ouput will be the expected one:

?
?

## Comparison

Available comparisons are the classical ones, where different is noted '<>':

var Int i j
var Bool c
c := i = j
c := i <> j
c := i < j
c := i > j
c := i <= j
c := i >= j

When you declare a new type, defining all operators above one after the other might be a bit boring, so support for all comparison operators can be provided as a single 'compare' instruction:

function compare a b -> c
arg Float a b ; arg Int c
...

The result is generally one of the three values 'compare_inferior', 'compare_equal' and 'compare_superior'.
Anyway, 'compare_diffent' can be returned in order to specify that the two values are different, but one cannot say if the second value is bigger or smaller than the first one. As an example, if floating point value 'undefined' is compared with floating point value '3.2'.
Lastly 'compare_unkown' could be returned to specify that comparison is just not possible, so that even returning 'compare_equal' or 'compare_different' is not possible.

Here is a sample direct usage of 'compare' function:

var Float a b
...
if ((compare a b) .and. compare_inferior+compare_superior+compare_different)<>0
console "Values are not equal" eol

of course, this is the same as:

if a<>b
console "Values are not equal" eol

## Booleans

There are two kind of booleans in Pliant:

var Bool i
var CBool j

'Bool' is a boolean stored on a single byte, 'CBool' is a C like boolean so stored on 4 bytes on a 32 bits platform and assumed to be true when and only when not zero. 'CBool' is more efficient because it can be stored in processor registers since it has 'atomic' property.

Operations or booleans are the classical ones:

var CBool k
k := not i
k := i and j
k := i or j

## Parser issue

Pliant does not use comma to separate parameters of a function. In math, if you write f(5,-2) you know that 'f' function has two parameters 5 and -2. But in Pliant, if you write (f 5 -2), does it mean that 'f' has also two parameters 5 and -2 or that 'f' has a single 3 parameter.

f 5 -2   # assume two parameters because minus has a space before and no space after
f 5-2    # assume one parameter
f 5 - 2  # assume one parameter