next up previous contents index
Next: Strings Up: ValuesTypes, and Constants Previous: Overview

Numeric Types

 

  boolean, byte, short, integer, float, and double types should be familiar to most programmers as Boolean, unsigned char (integer in the range 0 to 255), short integer, integer, single-precision floating-point, and double-precision floating-point types.

      complex and dcomplex types correspond to single-precision floating-point complex and double-precision floating-point complex numbers. These types are represented in Glish as a pair of floating-point numbers. One number is designated as the real portion and the other is designated as the imaginary portion of the complex number. In the case of complex, each of the numbers are single-precision, and in the case of dcomplex, each of the numbers are double-precision. There are two functions for accessing the components of these numbers.       real returns the real portion of a complex value, and       imag returns the imaginary portion of a complex value. These functions work on vectors of complex or dcomplex numbers. The length of the resultant vector is equal to the length of the vector argument.    

These types are referred to collectively as numeric. Numeric types can be used in arithmetic and logical operations (see § 3.2.3-§ 3.2.4 below) as well as in comparisons (§ 3.2.5, page gif). The maximum and minimum values for numeric types can be found by looking at system.limits.max and system.limits.min.

Numeric Constants

 

   There are two boolean constants:       T and F. They represent the values of ``true" and ``false", respectively.

  integer constants are just strings of digits, optionally preceded by a + or - sign: 1234, -42, and +5 for example.

  You write floating-point constants in the usual ways, a string of digits with perhaps a decimal point and perhaps a scale-factor written in scientific notation. Optional + or - signs may be given before the digits or before the scientific notation exponent. Examples are -1234., 3.14159, and .003e-23. All floating-point constants are of type double.

  dcomplex constants are written as a floating-point number followed by a + or - sign (this part is optional), followed by a second floating-point number which must be immediately, i.e. no whitespace, followed by an i. All complex constants are of type dcomplex. All of the following are valid:

    23.12-7.2i
    2.31+.003e-23i
    2.3i
    34 + 2i
When no extra white space exists within the complex constant, the number is translated directly to a complex constant, otherwise an addition (of two complex numbers) is performed. So in 34 + 2i, 34 is converted to a dcomplex value, and this value is added to 2i. If the i does not immediately follow the imaginary portion, as in 4 - 3 i, a runtime error results. Omitting the imaginary floating point number results in a reference to the variable i, if it happens to exist.

Mixing Numeric Types

 

  You can freely intermix numeric types in expressions. When intermixed, values are promoted to the ``highest" type in the expression.

In general, this promotion follows a simple hierarchy:

    (highest)

    dcomplex
    complex (*)
    double  (*)
    float
    integer
    short
    byte
    boolean

    (lowest)
where types are promoted upward (e.g., mixing a byte value and a float value will promote to float, since float appears higher in the list). The sole exception to this linear hierarchy is when mixing double values with complex values; these are always promoted to dcomplex, to preserve the precision of the double value. So if we had,
    a := [T, F, T]
    a[2] := 3.0
    a[3] := as_complex(-2+1i)
    b := [1, 2, 3]
    b[2] := 4-3i
a's type is initially boolean, becomes double with the first assignment, and finally becomes dcomplex after the last assignment to a. a ends up as a dcomplex despite the fact that a complex is assigned to it because a's type was double at the time of the assignment. b starts out as integer, but after the assignment, ends up dcomplex because complex constants are of type dcomplex.

When converting boolean   values to other numeric values, ``true" is promoted to 1 and false to 0. Thus the expression 5 + T yields the integer value 6 and 3.2 * 4 yields the double value 12.8. The type conversion functions can be used to prevent type promotion. For example,

    as_integer(3.2) * 4
yields the integer value 12. See § 9.2, page gif, for specifics on how each as_X function works. floor and ceiling can also be used to convert floating point values to integers (see § 9.2.2, page gif).

Arithmetic Operators

 

  For doing arithmetic, Glish supports + , - , * , / , % , and ^ . The first four have their usual meaning. They evaluate their operands after converting them   to the higher type of the two and return a result of that type. Division converts the operands to double and yields a double value, unless a complex or dcomplex value is involved. If a complex value is one of the division operands, the result is a dcomplex value. +  and -  can also be used as unary operators. For example,

    -[3, 5]
yields
    [-3, -5]

% computes a modulus, defined in the same way as in the C language. It evaluates its operands as integer and returns an integer result.

^ does exponentiation. It evaluates its operands as double values or dcomplex values if a complex number is involved and returns a double or dcomplex value of the same type as the evaluated operands. Thus

    3^5
returns the double value 243.0, but
    2+3i ^ 2
returns the dcomplex value -5+12i.

As discussed above in § 3.1.4, page gif,   the arithmetic operators all operate element-by-element when given two equal-sized vectors. For example,

    a := [1, 3, 5]
    b := a * 2:4
assigns to b
    [2, 9, 20]
If one of the vectors is a scalar then the scalar is paired with each element in turn:
    1:5 ^ 2
yields the double vector
    [1.0, 4.0, 9.0, 16.0, 25.0]
Operations on vectors of different sizes, such as
    1:5 ^ [2, 3]
result in run-time errors.

  Binary + and - have the lowest precedence, *, /, and % have equal and next highest precedence, and ^ has highest precedence of the binary operators. The precedence of ^ is just below that of the : operator discussed in § 3.1.4, page gif. The unary + and - operators have precedence just above :. See § 4.13, page gif, for a table of the precedence of all Glish operators.

  All arithmetic operators associate from left-to-right except for ^, which associates from right-to-left.

Finally, a number of arithmetic functions are also available, most of which operate element-by-element on their operands. See § 9.3, page gif, for descriptions.  

Logical Operators

 

  Glish supports three logical operators: & , | , and ! , are Boolean ``and", ``or", and ``not", respectively.

  The &, | operators require boolean operands, and other numeric types are not automatically converted to boolean in this case. As with the arithmetic   operators, these operate on multi-element vectors element by element. For example,

    [T, F, F, T] & [F, F, T, T]
yields
    [F, F, F, T]
while
    [T, F, F, T] | T
yields
    [T, T, T, T]
See § 4.5, page gif, for a discussion of the related && and || operators.

The unary ! operator negates its operand. It first converts any   numeric operand to boolean by treating a value of 0 (zero) as false and any other value as true. For example,

    ! [T, F, F, T]
yields
    [F, T, T, F]
and
    ! 5e-238
yields true.

  The logical operators are left-associative. The   | operator has precedence just below &, which in turn is just below that of the comparison operators (see § 3.2.5, page gif). The ! operator has very high precedence, the same as unary + and -; see § 3.2.3 and § 4.13.

§ 9.3, page gif, discusses the predefined functions for operating on logical values.  

Comparison Operators

 

  Glish provides the usual comparison operators: == , != , < , <= , > , and >= . They each take two operands, which   they convert to the higher of the two types (see § 3.2.2, page gif). They return a boolean vector corresponding to the element-by-element comparison of the operands. For example,

    3 < 3.000001
yields true, and
    1:4 == [3,2,3,2]
yields
    [F, T, T, F]
  The boolean value ``true" is considered greater than ``false". For example,
    F < T
yields true.

Comparisons are also defined for complex and dcomplex numbers. The result of a comparison operator applied to complex numbers is the result of the comparison applied to the real portion of those numbers. If however the real components of the complex numbers are equal, the result of the comparison is the comparison operator applied to the imaginary portion of the numbers. So the result of,

    3-2i < 4+7i
is true because, comparing the real components, 3 is less than 4. However,
    3+2i < 3-1i
is false because, now comparing the imaginary components since the real components are equal, 2 is not less than -1.

You can also use the == and != operators to compare non-numeric values. See § 4.4, page gif for details.

    The comparison operators are all non-associative and have equal precedence, just below that of binary + and - (see § 3.2.3, page gif) and just above that of the logical & operator (see § 3.2.4, page gif). See § 4.13, page gif, for a general discussion of precedence.  

Indexing With Numeric Types

You can use numeric values to index vectors in two different ways. boolean values serve as masks for picking out vector elements where some condition is true, and non-boolean values (converted to integer) serve as indices for specifying a particular set of elements in a vector. See § 3.6, page gif, for a discussion of these different ways of indexing.  


next up previous contents index
Next: Strings Up: ValuesTypes, and Constants Previous: Overview

Thu Nov 13 16:44:05 EST 1997