# symbol

© 2005,2007,2008,2012 John Abbott and Anna M. Bigatti
GNU Free Documentation License, Version 1.2

- Examples
- User documentation
  - Constructors
    - Creating a vector of symbols
  - Operations on symbols
    - Operations on vectors of symbols
- Maintainer documentation for symbol
- Bugs, Shortcomings and other ideas

CoCoALib Documentation Index

## Examples

- ex-symbol1.C
- ex-symbol2.C
- ex-PPMonoidElem1.C
- ex-PolyRing2.C

## User documentation

`symbol` is short for Symbolic Name. A value of type `symbol` represents a variable name possibly with some integer subscripts attached. Its primary use is for input and output of polynomials: the name of each indeterminate in a `PolyRing` is a `symbol`, similarly for a `PPMonoid`.

A `symbol` value has two components:

- head -- a string starting with a letter followed by letters and `_`s (note no digits or other characters allowed)
- subscripts -- a vector of machine integers, possibly empty (subscripts may be negative)

Examples of `symbol`s are: (in standard printed forms)

`x`, `X`, `alpha`, `z_alpha`, `x[2]`, `gamma[-2,3,-9]`

It is also possible to create anonymous symbols: they are used for building temporary polynomial extensions on unknown coefficient rings (which may contain any symbol) to guarantee no name conflicts.

- head -- is the empty string
- subscripts -- exactly one subscript

Each newly created anonymous symbol has a subscript strictly greater than that of any previous anonymous symbol. For better readability, an anonymous symbol prints out as a hash followed by the subscript: e.g. `#[12]`

### Constructors

Let `head` be a `std::string`, `ind`, `ind1`, `ind2`, `n` machine integers, `inds` a `std::vector<long>`.

- `symbol(head)` -- a `symbol` with no subscripts
- `symbol(head, ind)` -- a `symbol` with a single subscript
- `symbol(head, ind1, ind2)` -- a `symbol` with a two subscripts
- `symbol(head, inds)` -- a `symbol` with the given subscripts
- `NewSymbol()` -- a new anonymous symbol (prints as, for example, `#[12]`)

#### Creating a vector of symbols

Several polynomial ring pseudo-constructors expect a `vector` of `symbol`s to specify the names of the indeterminates. There are several convenience functions for constructing commonly used collections of `symbol`s.

- `symbols(hd1)` -- create vector of length 1 containing `symbol(hd1)`
- `symbols(hd1,hd2)` -- ... length 2...
- `symbols(hd1,hd2,hd3)` -- ... length 3...
- `symbols(hd1,hd2,hd3,hd4)` -- ... length 4...
- `SymbolRange(hd, lo, hi)` -- create vector of `hd[lo]`, `hd[lo+1]`, ... `hd[hi]`. Note that these symbols each have just a single subscript
- `SymbolRange(sym1, sym2)` -- create vector of cartesian product of the subscripts, e.g. given `x[1,3]` and `x[2,4]` produces `x[1,3]`, `x[1,4]`, `x[2,3]`, `x[2,4]`
- `NewSymbols(n)` -- `n` new anonymous symbols

### Operations on symbols

Let `sym`, `sym1`, and `sym2` be objects of type `symbol`

- `head(sym)` -- head of `sym` as a const ref to `std::string`
- `NumSubscripts(sym)` -- number of subscripts `sym` has (0 if sym has no subscripts)
- `subscript(sym, n)` -- gives `n`-th subscript of `sym`
- `cmp(sym1, sym2)` -- <0, =0, >0 according as `sym1` < = > `sym2` (for more info see Maintainer section)

- `sym1 < sym2` -- comparisons defined in terms of `cmp`
- `sym1 <= sym2` -- ...
- `sym1 > sym2` -- ...
- `sym1 >= sym2` -- ...
- `sym1 == sym2` -- ...
- `sym1 != sym2` -- ...

- `out << sym` -- print `sym` on `out`
- `in >> sym` -- read a symbol into `sym` (but also see Bugs section) (expected format is x, y[1], z[2,3], etc.)

#### Operations on vectors of symbols

- `AreDistinct(vecsyms)` -- true iff all symbols are distinct
- `AreArityConsistent(vecsyms)` -- true iff all symbols with the same head have the same arity

## Maintainer documentation for symbol

Note: I have used `MachineInt` as the type for fn args containing index values because it is safer, and I believe that the run-time penalty is unimportant. This is a considered exception to the guideline which says to use `long` for indexes.

I have decided not to allow big integers as subscripts because I don't see when it could ever be genuinely useful.

The implementation is extremely simple. Efficiency does not seem to be important (e.g. `symbols` and `SymbolRange` copy the vector upon returning). The implementation of `SymbolRange` is mildly delicate when we have to make checks to avoid integer overflow -- see comments in the code.

To make "anonymous" symbols I opted to use a private ctor which accepts just a single subscript; this ctor is called only by `NewSymbol` and `NewSymbols`.

The printing fn (`myOutputSelf`) has to check for an empty head, and if found it prints the string in `AnonHead`.

We believe a total ordering on `symbol`s could be useful; for instance, if someone wants to make a `std::map` using `symbol`s. Currently the total order is Lex on the heads then lex on the subscript vectors; this is simple, and is probably fast enough.

The function `symbol::myInput` is a stop-gap implementation.

## Bugs, Shortcomings and other ideas

The member function `myInput` handles white space wrongly. For CoCoALib whitespace is space, TAB, or backslash-newline; newline without backslash is not considered white space.

It might be nice to have a function which returns the vector of subscripts of a name.

I wonder what sending a `symbol` on an OpenMath channel would mean (given that OpenMath is supposed to preserve semantics, and a symbolic name is by definition devoid of semantics).