@comment -*-texinfo-*-
@comment This file was generated by doc2tex.pl from tricks.doc
@comment DO NOT EDIT DIRECTLY, BUT EDIT tricks.doc INSTEAD
@comment Id: tricks.tex,v 1.1 2003/08/08 14:27:06 pertusus Exp $
@comment this file contains the "Tricks and pittfals" sections

@c The following directives are necessary for proper compilation
@c with emacs (C-c C-e C-r).  Please keep it as it is.  Since it
@c is wrapped in `@ignore' and `@end ignore' it does not harm `tex' or
@c `makeinfo' but is a great help in editing this file (emacs
@c ignores the `@ignore').
@ignore
%**start
\input texinfo.tex
@setfilename tricks.hlp
@node Top, Tricks and pitfalls
@menu
* Tricks and pitfalls::
@end menu
@node Tricks and pitfalls, Examples, Functions and system variables, Top
@chapter Tricks and pitfalls
%**end
@end ignore

@menu
* Limitations::
* Major differences to the C programming language::
* Miscellaneous oddities::
* Identifier resolution::
@end menu

@c -------------------------------------------------------------------------
@node Limitations,Major differences to the C programming language,,Tricks and pitfalls
@section Limitations
@cindex Limitations

@sc{Singular} has the following limitations:
@itemize @bullet
@item
the characteristic of a prime field must be less than 2147483629 
@item
the (weighted) degree of a monomial must be smaller than the largest @code{long},
usually 2147483648
@item
the exponent of a ring variable must be smaller than 32768
unless the ring ordering start with the pseudo ordering 
@code{L(} max_exponent @code{)}
@item
the rank of any free module must be smaller than the largest @code{long},
usually 2147483648
@item
the number of parameters must be smaller than 32768
@item
the number of ring variables must be smaller than 32768
@item
the precision of long floating point numbers (for ground field @code{real})
must be smaller than 32768
@item
integers (of type @code{int}) have the limited range
from -2147483647 to 2147483647
@item
floating point numbers (type @code{number} from field @code{real}) have
a limited range which is machine dependent. A typical range is -1.0e-38
to 1.0e+38.  The string representation of overflow and underflow is
machine dependent, as well. For example "@code{Inf}" on Linux, or 
"@code{+.+00e+00}" on HPUX.
@c @item
@c a token (in the input) must have 16383 characters or less.
@c @*(Tokens are strings, blocks of statements, numbers)
@c @*This does not apply to proc in libraries but to blocks
@c within a procedure
@item
the length of an identifier is unlimited but @code{listvar}
displays only the first 20 characters
@c @item
@c the interpretation of text between a closing @code{@}} and the end of
@c the line is undefined. (Therefore do not put anything but spaces between
@c @code{@}} and the end of the line.)
@item
statements may not contain more than 10000 tokens
@item
@cindex German Umlaute
@cindex non-english special characters
@cindex special characters, non-english
All input to Singular must be 7-bit clean, i.e. special characters like the
the German Umlaute (@"a, @"o, etc.), or the French accent characters may 
neither appear as input to @sc{Singular}, nor in libraries or procedure
definitions.
@end itemize

@c -------------------------------------------------------------------------
@node Major differences to the C programming language,Miscellaneous oddities,Limitations,Tricks and pitfalls
@section Major differences to the C programming language
@cindex C programming language

Although many constructs from @sc{Singular}'s programming language are similar
to those from the C programming language, there are some subtle
differences. Most notably:

@menu
* No rvalue of increments and assignments::
* Evaluation of logical expressions::
* No case or switch statement::
* Usage of commas::
* Usage of brackets::
* Behavior of continue::
* Return type of procedures::
@end menu
@c ---------------------------------------
@node No rvalue of increments and assignments, Evaluation of logical expressions,,Major differences to the C programming language
@subsection No rvalue of increments and assignments
@cindex rvalue

The increment operator @code{++} (resp.@: decrement operator @code{--})
has no rvalue, i.e., cannot be used on the right-hand sides of
assignments.  So, instead of

@smallexample
j = i++;  // WRONG!!!
@end smallexample

@noindent (which results in an error), it must be written

@smallexample
i++; j = i;
@end smallexample

Likewise, an assignment expression does not have a result.  Therefore,
compound assignments like @code{i = j = k;} are not allowed and result
in an error.

@c ---------------------------------------
@node Evaluation of logical expressions, No case or switch statement, No rvalue of increments and assignments, Major differences to the C programming language
@subsection Evaluation of logical expressions
@cindex Evaluation of logical expressions
@cindex and
@cindex or

@c ------------------------------------------------------------
@c   This piece of text partially exists also in the file types.doc,
@c   chapter "boolean expressions".
@c   If you change something here, change it there, too!
@c ------------------------------------------------------------
@strong{All} arguments of a logical expression are first evaluated and
then the value of the logical expression is determined. For example, the
logical expressions @code{(a || b)} is evaluated by first evaluating
@code{a} @emph{and} @code{b}, even though the value of @code{b} has no
influence on the value of @code{(a || b)}, if @code{a} evaluates to
true. 

Note, that this evaluation is different from the left-to-right,
conditional evaluation of logical expressions (as found in most
programming languages). For example, in these other languages, the value
of @code{(1 || b)} is determined without ever evaluating @code{b}.  This
causes some problems with boolean tests on variables, which might not be
defined at evaluation time. For example, the following results in an
error, if the variable @code{i} is undefined:

@smallexample
if (defined(i) && i > 0) @{@} // WRONG!!!
@end smallexample

This must be written instead as:

@smallexample
if (defined(i))
@{
  if (i > 0) @{@}
@}
@end smallexample
@c ------------------------------------------------------------
@c end of duplicate text
@c ------------------------------------------------------------

However, there are several short work-arounds for this problem:
@enumerate
@item
If a variable (say, @code{i}) is only to be used as a boolean flag, then
define (value is TRUE) and undefine (value is FALSE) @code{i} instead of
assigning a value. Using this scheme, it is sufficient to simply write

@smallexample
if (defined(i))
@end smallexample

in order to check whether @code{i} is TRUE. Use the command @code{kill}
to undefine a variable, i.e.@: to assign it a FALSE value (@pxref{kill}).
@item
If a variable  can have more than two values, then
define it, if necessary, before it is used for the first time.
For example, if the following is used within a procedure

@smallexample
if (! defined(DEBUG)) @{ int DEBUG = 1;@}
@dots{}
if (DEBUG == 3)  @{@dots{}@}
if (DEBUG == 2)  @{@dots{}@}
@dots{}
@end smallexample

then a user of this procedure does not need to care about the existence
of the @code{DEBUG} variable -- this remains hidden from the
user. However, if @code{DEBUG} exists globally, then its local default
value is overwritten by its global one.
@end enumerate

@c ---------------------------------------
@node No case or switch statement,  Usage of commas, Evaluation of logical expressions, Major differences to the C programming language
@subsection No case or switch statement
@cindex case
@cindex switch

@sc{Singular} does not offer a @code{case} (or @code{switch})
statement. However, it can be imitated in the following way:

@smallexample
while (1)
@{
   if (choice == choice_1) @{ @dots{}; break;@}
   @dots{}
   if (choice == choice_n) @{ @dots{}; break;@}
   // default case
   @dots{}; break;
@}
@end smallexample

@c ---------------------------------------
@node Usage of commas, Usage of brackets, No case or switch statement, Major differences to the C programming language
@subsection Usage of commas
@cindex comma

In @sc{Singular}, a comma separates list elements and the value of a comma
expression is a list.
Hence, commas can not be used to combine several expressions into
a single expression. For example, instead of writing

@smallexample
for (i=1, j=5; i<5 || j<10; i++, j++) @{@dots{}@} // WRONG!!!!!!
@end smallexample

@noindent one has to write

@smallexample
for (i,j = 1,5; i<5 || j<10; i++, j++) @{@dots{}@}
@end smallexample

@c ---------------------------------------
@node Usage of brackets, Behavior of continue, Usage of commas, Major differences to the C programming language
@subsection Usage of brackets
@cindex bracket

In @sc{Singular}, curly brackets (@code{@{} @code{@}}) @strong{must
always} be used to enclose the statement body following such constructs
like @code{if}, @code{else}, @code{for}, or @code{while}, even if this
block consists of only a single statement. Similarly, in the return
statement of a procedure, parentheses (@code{(} @code{)}) @strong{must
always} be used to enclose the return value.  Even if there is no value
to return, parentheses have to be used after a return statement
(i.e., @code{return();}).  For example,

@smallexample
if (i == 1) return i;    // WRONG!!!!!
@end smallexample

@noindent results in an error. Instead, it must be written as

@smallexample
if (i == 1) @{ return (i); @}
@end smallexample

@c ---------------------------------------
@node  Behavior of continue, Return type of procedures, Usage of brackets, Major differences to the C programming language
@subsection Behavior of continue
@cindex continue
@sc{Singular}'s @code{continue} construct is only valid inside the body
of a @code{for} or @code{while} construct. It skips the rest of the
loop-body and jumps to the beginning of the block. Unlike the
C-construct @sc{Singular}'s @code{continue} @strong{does not execute the
increment statement}. For example,

@smallexample
for (int i = 1 ; i<=10; i=i+1)
@{
   @dots{}
   if (i==3) @{ i=8;continue; @}
     // skip the rest if i is 3 and
     // continue with the next i: 8
   i;
@}
@expansion{} 1
@expansion{} 2
@expansion{} 8
@expansion{} 9
@expansion{} 10
@end smallexample
@c ---------------------------------------
@node Return type of procedures,,Behavior of continue, Major differences to the C programming language
@subsection Return type of procedures
@cindex return type of procedures

Although the @sc{Singular} language is a strongly typed programming
language, the type of the
return value of a procedure does not need to be specified. As a
consequence, the return type of a procedure may vary, i.e., may, for
example, depend on the input. However, the return value
of such a procedure may then only be assigned to a variable of type
@code{def}.

@smallexample
@c reused example Return_type_of_procedures tricks.doc:308 
proc type_return (int i)
@{
  if (i > 0) @{return (i);@}
  else @{return (list(i));@}
@}
def t1 = type_return(1);
def t2 = type_return(-1);
typeof(t1); typeof(t2);
@expansion{} int
@expansion{} list
@c end example Return_type_of_procedures tricks.doc:308
@end smallexample

Furthermore, it is mandatory to assign the return value of a procedure
to a variable of type @code{def}, if a procedure changes the current
ring using the @code{keepring} command (@pxref{keepring}) and returns a
ring-dependent value (like a polynomial or module).

@smallexample
@c reused example Return_type_of_procedures_1 tricks.doc:326 
proc def_return
@{
  ring r=0,(x,y),dp;
  poly p = x;
  keepring r;
  return (x);
@}
def p = def_return();
// poly p = def_return(); would be WRONG!!!
typeof(p);
@expansion{} poly
@c end example Return_type_of_procedures_1 tricks.doc:326
@end smallexample

On the other hand, more than one value can be returned by a single
@code{return} statement. For example,

@smallexample
proc tworeturn () @{ return (1,2); @}
int i,j = tworeturn();
@end smallexample


@c -------------------------------------------------------------------------
@node Miscellaneous oddities, Identifier resolution, Major differences to the C programming language, Tricks and pitfalls
@section Miscellaneous oddities

@enumerate
@item integer division
@cindex integer division
@cindex div

If two numerical constants (i.e., two sequences of digits) are divided
using the @code{/} operator, the surrounding whitespace determines
which division to use: if there is no space between the constants and
the @code{/} operator (e.g., "3/2"), both numerical constants are
treated as of type @code{number} and the current ring division is
used. If there is at least one space surrounding the @code{/} operator
(e.g., "3 / 2"), both numerical constants are treated as of type
@code{int} and an integer division is performed. To avoid confusion, use
the @code{div} operator instead of @code{/} for integer division and an
explicit type cast to @code{number} for ring division. Note, that this
problem does only occur for divisions of numerical constants.
@smallexample
@c reused example Miscellaneous_oddities tricks.doc:370 
  ring r=32002,x,dp;
  3/2;    // ring division
@expansion{} -15994
  3 / 2;  // integer division
@expansion{} 1
  3 div 2;
@expansion{} 1
  number(3) / number(2);
@expansion{} -15994
  number a=3;
  number b=2;
  a/b;
@expansion{} -15994
  int c=3;
  int d=2;
  c / d;
@expansion{} 1
@c end example Miscellaneous_oddities tricks.doc:370
@end smallexample


@item monomials and precedence
@cindex monomials and precedence

The computation of a monomial has precedence over all operators:
@smallexample
@c reused example Miscellaneous_oddities_1 tricks.doc:391 
  ring r=0,(x,y),dp;
  2xy^2 == (2*x*y)^2;
@expansion{} 1
  2xy^2 == 2x*y^2;
@expansion{} 0
  2x*y^2 == 2*x * (y^2);
@expansion{} 1
@c end example Miscellaneous_oddities_1 tricks.doc:391
@end smallexample

@item meaning of @code{mult}
@cindex mult
@cindex degree

For an arbitrary ideal or module @code{i}, @code{mult(i)} returns the
multiplicity of the ideal generated by the leading monomials of the
given generators of @code{i}, hence depends on the monomial ordering!

A standard mistake is to interpret @code{degree(i)} or @code{mult(i)}
for an inhomogeneous ideal @code{i} as the degree of the homogenization
or as something like the 'degree of the affine part'. For the ordering
@code{dp} (degree reverse lexicographical) the converse is true: if
@code{i} is given by a standard basis, @code{mult(i)} is the degree of
the homogeneous ideal obtained by homogenization of @code{i} and then
putting the homogenizing variable to 0, hence it is the degree of the
part at infinity (this can also be checked by looking at the initial
ideal).

@item size of ideals
@cindex ideals
@cindex size

@code{size} counts the non-zero entries of an ideal or module. Use
@code{ncols} to determine the actual number of entries in the ideal or module.

@item computations in @code{qring}
@cindex qring

In order to speed up computations in quotient rings, @sc{Singular}
usually does not reduce polynomials w.r.t.@: the quotient ideal; rather
the given representative is used as long as possible during
computations. If it is necessary, reduction is done during standard base
computations. To reduce a polynomial @code{f} by hand w.r.t.@: the
current quotient ideal use the command @code{reduce(f,std(0))}
(@pxref{reduce}).

@item substring selection
@cindex string

To extract substrings from a @code{string}, square brackets are used,
enclosing either two comma-separated @code{int}s or an
@code{intvec}. Although two comma-separated @code{int}s represent an
@code{intvec}, they mean different things in substring access. Square
brackets enclosing two @code{int}s (e.g.@: @code{s[2,6]}) return a
substring where the first integer denotes the starting position and the
second integer denotes the length of the substring. The result is
returned as a @code{string}. Square brackets enclosing an @code{intvec}
(e.g.@: @code{s[intvec(2,6)]}) return the characters of the string at the
position given by the values of the @code{intvec}. The result is
returned as an expression list of strings. 
@c  Note, that this problem does
@c  not occur for square brackets enclosing a single @code{int} or more than
@c  two @code{int}s. Those always return an expression list of strings.

@smallexample
@c reused example Miscellaneous_oddities_2 tricks.doc:454 
  string s = "one-word";
  s[2,6];     // a substring starting at the second char
@expansion{} ne-wor
  size(_);
@expansion{} 6
  intvec v = 2,6;
  s[v];      // the second and the sixth char
@expansion{} n o
  string st = s[v];  // stick together by an assignment
  st;
@expansion{} no
  size(_);
@expansion{} 2
  v = 2,6,8;
  s[v];
@expansion{} n o d
@c end example Miscellaneous_oddities_2 tricks.doc:454
@end smallexample

@ifset namespaces
@item packages and indexed variables

See example
@smallexample
@c reused example Miscellaneous_oddities_3 tricks.doc:473 
package K;
string K::varok;
@expansion{}    ? package is not supported in this version
@expansion{}    ? object to declare is not a name
@expansion{}    ? error occurred in line 2: `string K::varok;`
@expansion{}    ? wrong type declaration. type 'help string;'
string K::donotwork(1);
@expansion{}    ? package is not supported in this version
@expansion{}    ? error occurred in line 3: `string K::donotwork(1);`
@expansion{}    ? wrong type declaration. type 'help string;'
int K::i(1..3);
@expansion{}    ? package is not supported in this version
@expansion{}    ? error occurred in line 4: `int K::i(1..3);`
@expansion{}    ? wrong type declaration. type 'help int;'
// Toplevel does not contain i(1..3)
listvar();
@expansion{} // K                    [0]  package (N)
@expansion{} // LIB                  [0]  string standard.lib
// i(1..3) are stored in Package 'K'
listvar(K);
@expansion{} // K                    [0]  package (N)
@c end example Miscellaneous_oddities_3 tricks.doc:473
@end smallexample
@end ifset

@end enumerate

@c ----------------------------------------------
@node Identifier resolution,, Miscellaneous oddities, Tricks and pitfalls
@section Identifier resolution
@cindex identifier

In @sc{Singular}, an identifier (i.e., a "word") is resolved in the
following way and order: It is checked for
@enumerate
@item
a reserved name (like @code{ring}, @code{std}, @dots{}),
@item
a local  variable (w.r.t. a procedure),
@item
a local ring variable (w.r.t. the current basering locally set in a procedure),
@item
a global variable,
@item
a global ring variable (w.r.t. the current basering)
@item
a monomial consisting of local ring variables written without operators,
@item
a monomial consisting of global ring variables written without operators.
@end enumerate

Consequently, it is allowed to have general variables with the same name
as ring  variables. However, the above identifier resolution order must
be kept in mind. Otherwise, surprising results may come up.

@smallexample
@c reused example Identifier_resolution tricks.doc:517 
ring r=0,(x,y),dp;
int x;
x*y; // resolved product int*poly, i.e., 0*y
@expansion{} 0
xy; // "xy" is one identifier and resolved to monomial xy
@expansion{} xy
@c end example Identifier_resolution tricks.doc:517
@end smallexample

For these reasons, we strongly recommend not to use variables which
have the same name(s) as ring variables.

Moreover, we strongly recommend not to use ring variables whose name is
fully contained in (i.e., is a substring of) another name of a ring
variable. Otherwise, effects like the following might occur:


@smallexample
@c reused example Identifier_resolution_1 tricks.doc:534 
ring r=0,(x, x1),dp; // name x is substring of name x1 !!!!!!!!!
x;x1;   // resolved poly x
@expansion{} x
@expansion{} x1
short=0; 2x1; // resolved to monomial 2*x^1 !!!!!!
@expansion{} 2*x
2*x1; // resolved to product 2 times x1
@expansion{} 2*x1
@c end example Identifier_resolution_1 tricks.doc:534
@end smallexample
