symbol
is short for "Symbolic Name". A value of type symbol
represents a "variable name" possibly with some integer indices
attached. Its primary use is for input and output of polynomials: the
name of each indeterminate in a polynomial ring is a symbol
, similarly
for a PPMonoid
.
A symbol
value has two components: its head which is a string
comprising letters and underscores (but the first character must be a
letter), and its indices which are a vector of integers (indices may be
negative). Examples of symbol
s are: (in standard printed forms)
x, X, alpha, z_alpha, x[2], gamma[-2,3,-9]
symbol(head)
where head is a std::string
symbol
with no indices
symbol(head, ind)
where head is a std::string
and ind
is a machine integersymbol
with a single index
symbol(head, ind1, ind2)
where head is a std::string
and ind1
& ind2
are machine integerssymbol
with a two indexes
symbol(head, inds)
where head is a std::string
andinds
is a std::vector<long>
this produces a symbol
with the given indices
Let sym, sym1, and sym2 be objects of type symbol
head(sym) head of sym as a const ref to ``std::string`` NumIndices(sym) number of indices sym has (gives 0 if sym has no indices) index(sym, n) gives n-th index 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.)
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 index (see next fn to make a range of symbols which have more than one index) SymbolRange(sym1, sym2) create vector of "cartesian product" of the indices, e.g. given x[1,3] and x[2,4] produces x[1,3], x[1,4], x[2,3], x[2,4] AreDistinct(vecsyms) true iff all symbols are distinct AreArityConsistent(vecsyms) true iff all symbols with the same head have the same arity
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.
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 index vectors"; this is
simple, and is probably fast enough.
The function symbol::myInput
is a stop-gap implementation.
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 indices of a name.
Decided not to permit big integers as indices; I don't see when it could ever be useful.
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).