Commit 81982356 authored by Jiri (George) Lebl's avatar Jiri (George) Lebl Committed by George Lebl

Much nicer pretty printing of matrices. Rather than using tabs, use commas


Thu Nov 15 23:30:51 2007  Jiri (George) Lebl <jirka@5z.com>

	* src/calc.c: Much nicer pretty printing of matrices.  Rather
	  than using tabs, use commas and align elements successive rows.
	  Both nicer, more readable (when MixedFractions is on) and more
	  compact way of seeing matrices.  Yay!

	* src/lexer.l: drop the tab support for entering matrices.  Not only
	  was it stupid, it didn't work on the command line

	* src/funclib.c: fix print, printn and display functions to not follow
	  the line length limits like normal output

	* src/calc.c: when pretty printing a matrix, only print the leading
	  newline if we are not in fact on the start of a line

	* configure.in: check for svn rather than cvs to add extra warnings

	* src/gnome-genius.c: make is_uri static to avoid a warning

	* help/C/genius.xml: update the manual

	* NEWS: update


svn path=/trunk/; revision=614
parent fe6fcf3d
Thu Nov 15 23:30:51 2007 Jiri (George) Lebl <jirka@5z.com>
* src/calc.c: Much nicer pretty printing of matrices. Rather
than using tabs, use commas and align elements successive rows.
Both nicer, more readable (when MixedFractions is on) and more
compact way of seeing matrices. Yay!
* src/lexer.l: drop the tab support for entering matrices. Not only
was it stupid, it didn't work on the command line
* src/funclib.c: fix print, printn and display functions to not follow
the line length limits like normal output
* src/calc.c: when pretty printing a matrix, only print the leading
newline if we are not in fact on the start of a line
* configure.in: check for svn rather than cvs to add extra warnings
* src/gnome-genius.c: make is_uri static to avoid a warning
* help/C/genius.xml: update the manual
* NEWS: update
Thu Nov 15 18:39:06 2007 Jiri (George) Lebl <jirka@5z.com>
* src/Makefile.am: add nullspacetest.gel
......
......@@ -36,6 +36,8 @@ DISTCLEANFILES = \
intltool-merge \
intltool-update
DISTCHECK_CONFIGURE_FLAGS = --disable-scrollkeeper --disable-update-mimedb
# This doesn't add the graphing functions
#genius-function-list.txt: src/genius
# LANG=C src/genius --version > genius-function-list.txt
......
Changes to 1.0.1
Syntax and semantical changes are marked with CHANGE:
* GNOME version can now show listing of all user defined global and local
variables (can display this even while the engine is running, including
a "backtrace" to aid debugging)
......@@ -8,12 +10,16 @@ Changes to 1.0.1
causing the computer to grind to a halt.
* When printing floating point numbers always make sure it is obvious that
these are floating point by appending .0 when they would look like integers.
* Matrix printing is much nicer now, and possible to copy and paste back in
* Add IsMatrixPositive, IsMatrixNonnegative, version, IsZero, IsIdentity,
DividePoly, IsSubset
* PivotColumns and NullSpace are built in for greater speed.
* CHANGE: Drop the support for tab as a matrix separator, it didn't
work properly, especialy not on the command line
* CHANGE: Remove IsGaussianInteger, we already have IsGaussInteger alias
IsComplexInteger
* CHANGE: OrthogonalComplement is with respect to the Hermitian product
* CHANGE: display, printn and print don't follow FullExpressions=false
* The .desktop file now has different Categories setup so will likely appear
in "Education" or "Accessories" menu rather than "Office"
* Chop small numbers when they appear near other larger numbers. New
......
......@@ -195,7 +195,7 @@ dnl ******************************
AC_ARG_ENABLE(more-warnings,
[ --enable-more-warnings Maximum compiler warnings],
set_more_warnings="$enableval",[
if test -f $srcdir/CVS/Root; then
if test -f $srcdir/.svn/entries; then
is_cvs_version=true
set_more_warnings=yes
else
......
......@@ -81,9 +81,9 @@
2.2. When You Start Genius
3. Basic usage
3. Basic Usage
3.1. Using the work area
3.1. Using the Work Area
3.2. To Create a New Program
......@@ -113,27 +113,27 @@
5.2.1. Setting Variables
5.2.2. Built-in variables
5.2.2. Built-in Variables
5.2.3. Previous result variable
5.2.3. Previous Result Variable
5.3. Using Functions
5.3.1. Defining functions
5.3.1. Defining Functions
5.3.2. Variable argument lists
5.3.2. Variable Argument Lists
5.3.3. Passing functions to functions
5.3.3. Passing Functions to Functions
5.3.4. Operations on functions
5.3.4. Operations on Functions
5.4. Absolute value / Modulus
5.4. Absolute Value / Modulus
5.5. Separator
5.6. Modular evaluation
5.6. Modular Evaluation
5.7. List of GEL operators
5.7. List of GEL Operators
6. Programming with GEL
......@@ -141,19 +141,19 @@
6.2. Loops
6.2.1. While loops
6.2.1. While Loops
6.2.2. For loops
6.2.2. For Loops
6.2.3. Foreach loops
6.2.3. Foreach Loops
6.2.4. Break and continue
6.2.4. Break and Continue
6.3. Sums and products
6.3. Sums and Products
6.4. Comparison operators
6.4. Comparison Operators
6.5. Global variables and scope of variables
6.5. Global Variables and Scope of Variables
6.6. Returning
......@@ -163,17 +163,19 @@
7. Advanced Programming with GEL
7.1. Error handling
7.1. Error Handling
7.2. GEL startup procedure
7.2. Toplevel Syntax
7.3. Loading programs
7.3. GEL Startup Procedure
7.4. Loading Programs
8. Matrices in GEL
8.1. Matrix support
8.1. Entering Matrices
8.2. Conjugate transpose and transpose operator
8.2. Conjugate Transpose and Transpose Operator
8.3. Linear Algebra
......@@ -225,7 +227,7 @@
11.19. Plotting
12. Example programs in GEL
12. Example Programs in GEL
13. Settings
......@@ -251,7 +253,7 @@
4-4. Parametric Plot
4-5. Surface plot
4-5. Surface Plot
----------------------------------------------------------------------
......@@ -296,17 +298,21 @@
item name you are looking for is Genius Math Tool. Once you locate
this menu item click on it to start Genius Mathematics Tool.
Note that depending on your system installation this menu item
may not be available. If it is not, you can open the Run dialog
and executing gnome-genius.
Run dialog
Depending on your system installation the menu item may not be
available. If it is not, you can open the Run dialog and execute
gnome-genius.
Command line
Execute the following command: genius. Note that this will start
the command line only version of genius, the graphical environment
will not start and some functions such as plotting will not be
available. To start the full GNOME version of Genius execute
gnome-genius.
To start the GNOME version of Genius Mathematics Tool execute
gnome-genius from the command line.
To start the command line only version, execute the following
command: genius. This version does not include the graphical
environment and some functionality such as plotting will not be
available.
----------------------------------------------------------------------
......@@ -359,9 +365,9 @@
----------------------------------------------------------------------
Chapter 3. Basic usage
Chapter 3. Basic Usage
3.1. Using the work area
3.1. Using the Work Area
Normally you interact with the calculator in the Console tab of the work
area. If you are running the text only version then the console will be
......@@ -516,7 +522,7 @@
to |cos(x+1i*y)|. See Figure 4-5. For plotting using the command line see
the documentation of the SurfacePlot function.
Figure 4-5. Surface plot
Figure 4-5. Surface Plot
----------------------------------------------------------------------
......@@ -747,7 +753,7 @@
----------------------------------------------------------------------
5.2.2. Built-in variables
5.2.2. Built-in Variables
GEL has a number of built-in `variables', such as e, pi or GoldenRatio.
These are widely used constants with a preset value, and they cannot be
......@@ -756,7 +762,7 @@
----------------------------------------------------------------------
5.2.3. Previous result variable
5.2.3. Previous Result Variable
The Ans and ans variables can be used to get the result of the last
expression. For example, if you had performed some calculation, to add 389
......@@ -799,7 +805,7 @@
----------------------------------------------------------------------
5.3.1. Defining functions
5.3.1. Defining Functions
Syntax:
......@@ -821,7 +827,7 @@
----------------------------------------------------------------------
5.3.2. Variable argument lists
5.3.2. Variable Argument Lists
If you include ... after the last argument name in the function
declaration, then Genius will allow any number of arguments to be passed
......@@ -835,7 +841,7 @@
----------------------------------------------------------------------
5.3.3. Passing functions to functions
5.3.3. Passing Functions to Functions
In Genius, it is possible to pass a function as an argument to another
function. This can be done using either `function nodes' or anonymous
......@@ -864,7 +870,7 @@
----------------------------------------------------------------------
5.3.4. Operations on functions
5.3.4. Operations on Functions
Some functions allow arithmetic operations, and some single argument
functions such as exp or ln, to operate on the function. For example,
......@@ -890,7 +896,7 @@
----------------------------------------------------------------------
5.4. Absolute value / Modulus
5.4. Absolute Value / Modulus
You can make an absolute value of something by putting the |'s around it.
For example:
......@@ -927,7 +933,7 @@
----------------------------------------------------------------------
5.6. Modular evaluation
5.6. Modular Evaluation
Sometimes when working with large numbers, it might be faster if results
are modded after each calculation. To use it you just add "mod <integer>"
......@@ -956,7 +962,7 @@
genius> sqrt(4) mod 7
=
[2 5]
[2, 5]
genius> 2*2 mod 7
= 4
......@@ -964,7 +970,7 @@
----------------------------------------------------------------------
5.7. List of GEL operators
5.7. List of GEL Operators
As everything in gel is really just an expression, it is really just all
connected together with operators. Here is a list of the operators in GEL.
......@@ -1172,7 +1178,7 @@
genius> 1:2:9
=
`[1 3 5 7 9]
`[1, 3, 5, 7, 9]
(a)i
......@@ -1240,7 +1246,7 @@
6.2. Loops
6.2.1. While loops
6.2.1. While Loops
Syntax:
......@@ -1255,7 +1261,7 @@
----------------------------------------------------------------------
6.2.2. For loops
6.2.2. For Loops
Syntax:
......@@ -1276,7 +1282,7 @@
----------------------------------------------------------------------
6.2.3. Foreach loops
6.2.3. Foreach Loops
Syntax:
......@@ -1297,7 +1303,7 @@
----------------------------------------------------------------------
6.2.4. Break and continue
6.2.4. Break and Continue
You can also use the break and continue commands in loops. The continue
continue command will restart the current loop at its next iteration,
......@@ -1311,7 +1317,7 @@
----------------------------------------------------------------------
6.3. Sums and products
6.3. Sums and Products
Syntax:
......@@ -1331,7 +1337,7 @@
----------------------------------------------------------------------
6.4. Comparison operators
6.4. Comparison Operators
The following standard comparison operators are supported in GEL and
have the obvious meaning: ==, >=, <=, !=, <>, <, >. They return true or
......@@ -1362,7 +1368,7 @@
----------------------------------------------------------------------
6.5. Global variables and scope of variables
6.5. Global Variables and Scope of Variables
Like most programming languages, GEL has two different types of
variables: local and global. A local variable only exists in the context
......@@ -1504,19 +1510,61 @@
Chapter 7. Advanced Programming with GEL
7.1. Error handling
7.1. Error Handling
If you detect an error in your function, you can bail out of it. For
normal errors, such as wrong types of arguments, you can fail to compute
the function by adding the empty statement bailout. If something went
really wrong and you want to completely kill the current computation, you
can use exception.
the function by adding the statement bailout. If something went really
wrong and you want to completely kill the current computation, you can use
exception.
Look at lib.gel for some examples.
For example if you want to check for arguments in your function. You
could use the following code.
function f(M) = (
if not IsMatrix (M) then (
error ("M not a matrix!");
bailout
);
...
)
----------------------------------------------------------------------
7.2. GEL startup procedure
7.2. Toplevel Syntax
The synatax is slightly different if you enter statements on the top
level versus when they are inside parentheses or inside functions. On the
top level, enter acts the same as if you press return on the command line.
Therefore think of programs as just sequence of lines as if were entered
on the command line. In particular, you do not need to enter the separator
at the end of the line (unless it is of course part of several statements
inside parenteses).
The following code will produce an error when entered on the top level
of a program, while it will work just fine in a function.
if Something() then
DoSomething()
else
DoSomethingElse()
The problem is that after Genius Mathematics Tool sees the end of line
after the second line, it will decide that we have whole statement and it
will execute it. After the execution is done, Genius Mathematics Tool will
go on to the next line, it will see else, and it will produce a parsing
error. To fix this, use parentheses. Genius Mathematics Tool will not be
satisfied until it has found that all parenteses are closed.
if Something() then (
DoSomething()
) else (
DoSomethingElse()
)
----------------------------------------------------------------------
7.3. GEL Startup Procedure
First the program looks for the installed library file (the compiled
version lib.cgel) in the installed directory, then it looks into the
......@@ -1528,7 +1576,7 @@
----------------------------------------------------------------------
7.3. Loading programs
7.4. Loading Programs
Sometimes you have a larger program that you wrote into a file and want
to read in that file. In these situations, you have two options. You can
......@@ -1556,14 +1604,18 @@
Chapter 8. Matrices in GEL
8.1. Matrix support
Genius has support for vectors and matrices and a sizable library of
matrix manipulation and linear algebra functions.
----------------------------------------------------------------------
8.1. Entering Matrices
To enter matrixes, you can use one of the following two syntaxes. You can
either enter the matrix on one line, separating values by commas and rows
by semicolons. Or you can enter each row on one line, separating values by
commas or tabs. (Note that tabs are not usually easily possible on the
console, only in files). You can also just combine the two methods. So to
enter a 3x3 matrix of numbers 1-9 you could do
commas. You can also just combine the two methods. So to enter a 3x3
matrix of numbers 1-9 you could do
[1,2,3;4,5,6;7,8,9]
......@@ -1573,14 +1625,7 @@
4, 5, 6
7, 8, 9]
or (where the empty spaces are tabs)
[1 2 3
4 5 6
7 8 9]
Do not use both ';' and return at once on the same line though. Also do
not mix tabs and commas. It is just safest to use commas as separators.
Do not use both ';' and return at once on the same line though.
You can also use the matrix expansion functionality to enter matricies.
For example you can do:
......@@ -1593,10 +1638,10 @@
and you should get
[1 2 3 10
4 5 6 10
7 8 9 10
11 11 11 12]
[1, 2, 3, 10
4, 5, 6, 10
7, 8, 9, 10
11, 11, 11, 12]
similiarly you can build matricies out of vectors and other stuff like
that.
......@@ -1609,20 +1654,20 @@
will end up being
[1 2 3
4 5 0
6 0 0]
[1, 2, 3
4, 5, 0
6, 0, 0]
When matrices are evaluated, they are evaluated and traversed row-wise.
This is just like the M@(j) operator which traverses the matrix row-wise.
Note Be careful about using whitespace and returns for expressions inside
the [ ] brackets, as they have a slightly different meaning and could
mess you up.
Note Be careful about using returns for expressions inside the [ ]
brackets, as they have a slightly different meaning there. You will
start a new row.
----------------------------------------------------------------------
8.2. Conjugate transpose and transpose operator
8.2. Conjugate Transpose and Transpose Operator
You can conjugate transpose a matrix by using the ' operator. That is the
entry in the ith column and the jth row will be the complex conjugate of
......@@ -1748,13 +1793,13 @@
will just return a new vector where every element is unique.
genius> MakeSet([1,2,2,3])
= [1 2 3]
= [1, 2, 3]
Similarly there are functions Union, Intersection, SetMinus, which are
rather self explanatory. For example:
genius> Union([1,2,3], [1,2,4])
= [1 2 4 3]
= [1, 2, 4, 3]
Note that no order is guaranteed for the return values. If you wish to
sort the vector you should use the SortVector function.
......@@ -5230,7 +5275,7 @@
----------------------------------------------------------------------
Chapter 12. Example programs in GEL
Chapter 12. Example Programs in GEL
Here is a function that calculates factorials:
......@@ -5317,7 +5362,7 @@
to the ones provided by the standard library. These control how the
calculator behaves.
Note Changing settings with GEL
Note Changing Settings with GEL
Many of the settings in Genius are simply global variables, and can
be evaluated and assigned to in the same way as normal variables. See
Section 5.2 about evaluating and assigning to variables, and Section
......
......@@ -202,10 +202,15 @@
<guimenuitem>Genius Math Tool</guimenuitem>. Once you locate
this menu item click on it to start &app;.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Run</guilabel> dialog</term>
<listitem>
<para>
Note that depending on your system installation this menu item
Depending on your system installation the menu item
may not be available. If it is not, you can open the Run dialog
and executing <command>gnome-genius</command>.
and execute <command>gnome-genius</command>.
</para>
</listitem>
</varlistentry>
......@@ -213,12 +218,14 @@
<term>Command line</term>
<listitem>
<para>
Execute the following command: <command>genius</command>.
Note that this will start the command line only version of
genius, the graphical environment will not start and some
functions such as plotting will not be available. To start the
full GNOME version of Genius execute
<command>gnome-genius</command>.
To start the GNOME version of &app; execute
<command>gnome-genius</command> from the command line.
</para>
<para>
To start the command line only version,
execute the following command: <command>genius</command>.
This version does not include the graphical environment
and some functionality such as plotting will not be available.
</para>
</listitem>
</varlistentry>
......@@ -310,10 +317,10 @@ variables. Finally it allows plotting functions using a user friendly dialog bo
<!-- ================ Usage =================================== -->
<chapter id="genius-usage">
<title>Basic usage</title>
<title>Basic Usage</title>
<sect1 id="genius-usage-workarea">
<title>Using the work area</title>
<title>Using the Work Area</title>
<para>
Normally you interact with the calculator in the <guilabel>Console</guilabel> tab of the
......@@ -569,7 +576,7 @@ See <xref linkend="lineplot-fig"/>.
</para>
<figure id="surfaceplot-fig">
<title>Surface plot</title>
<title>Surface Plot</title>
<screenshot>
<mediaobject>
<imageobject>
......@@ -822,7 +829,7 @@ linkend="genius-gel-variables-global"/>.
</sect2>
<sect2 id="genius-gel-variables-built-in">
<title>Built-in variables</title>
<title>Built-in Variables</title>
<para>
GEL has a number of built-in &lsquo;variables&rsquo;, such as
<varname>e</varname>, <varname>pi</varname> or <varname>GoldenRatio</varname>. These are widely used constants with a preset value, and
......@@ -834,7 +841,7 @@ See <xref linkend="genius-gel-function-list-constants" /> for a full list.
<sect2 id="genius-gel-previous-result">
<title>Previous result variable</title>
<title>Previous Result Variable</title>
<para>
The <varname>Ans</varname> and <varname>ans</varname> variables can be used to get the result of the last expression. For example, if you had performed some calculation, to add 389 to the result you could do:
<programlisting>Ans+389
......@@ -879,7 +886,7 @@ The names of functions are case sensitive. That means that functions named <func
<sect2 id="genius-gel-functions-defining">
<title>Defining functions</title>
<title>Defining Functions</title>
<para>
Syntax:
<programlisting><![CDATA[function <identifier>(<comma separated arguments>) = <function body>
......@@ -898,7 +905,7 @@ then <userinput>addup(1,4,9)</userinput> yields 14
</sect2>
<sect2 id="genius-gel-functions-variable-argument-lists">
<title>Variable argument lists</title>
<title>Variable Argument Lists</title>
<para>
If you include <literal>...</literal> after the last argument name in the function declaration, then &appname; will allow any number of arguments to be passed in place of that argument. If no arguments were passed then that argument will be set to <constant>null</constant>. Otherwise, it will be a horizontal vector containing all the arguments. For example:
<programlisting>function f(a,b...) = b
......@@ -909,7 +916,7 @@ Then <userinput>f(1,2,3)</userinput> yields <computeroutput>[2,3]</computeroutpu
<sect2 id="genius-gel-functions-passing-functions">
<title>Passing functions to functions</title>
<title>Passing Functions to Functions</title>
<para>
In &appname;, it is possible to pass a function as an argument to another function. This can be done using either &lsquo;function nodes&rsquo; or anonymous functions.
......@@ -939,7 +946,7 @@ f(`(x) = x*x,2)
<sect2 id="genius-gel-functions-operations">
<title>Operations on functions</title>
<title>Operations on Functions</title>
<para>
Some functions allow arithmetic operations, and some single argument functions such as <function>exp</function> or <function>ln</function>, to operate on the function. For example,
<programlisting>exp(sin*cos+4)
......@@ -966,7 +973,7 @@ Not all functions can be used in this way. In addition, when you use a binary op
</sect1>
<sect1 id="genius-gel-absolute-value-modulus">
<title>Absolute value / Modulus</title>
<title>Absolute Value / Modulus</title>
<para>
You can make an absolute value of something by putting the
<literal>|</literal>'s around it. For example:
......@@ -1007,7 +1014,7 @@ the code if it is executed too often as there is one more operator involved.
</sect1>
<sect1 id="genius-gel-modular-evaluation">
<title>Modular evaluation</title>
<title>Modular Evaluation</title>
<para>
Sometimes when working with large numbers, it might be faster if results are
modded after each calculation. To use it you just add "mod &lt;integer&gt;" after
......@@ -1035,7 +1042,7 @@ discrete versions working within the ring of integers you selected. For
example:
<programlisting>genius> sqrt(4) mod 7
=
[2 5]
[2, 5]
genius> 2*2 mod 7
= 4</programlisting>
<function>sqrt</function> will actually return all the possible square
......@@ -1044,7 +1051,7 @@ genius> 2*2 mod 7
</sect1>
<sect1 id="genius-gel-operator-list">
<title>List of GEL operators</title>
<title>List of GEL Operators</title>
<para>
As everything in gel is really just an expression, it is really just
......@@ -1530,7 +1537,7 @@ different from <literal>=</literal> because it never gets translated to a
with <varname>b</varname> as a step. That is for example
<programlisting>genius> 1:2:9
=
`[1 3 5 7 9]
`[1, 3, 5, 7, 9]
</programlisting>
</para>
</listitem>
......@@ -1622,7 +1629,7 @@ will be interpreted as:
<title>Loops</title>
<sect2 id="genius-gel-loops-while">
<title>While loops</title>
<title>While Loops</title>
<para>
Syntax:
<programlisting><![CDATA[while <expression1> do <expression2>
......@@ -1635,7 +1642,7 @@ These are similiar to other languages, however they return the result of the las
</sect2>
<sect2 id="genius-gel-loops-for">
<title>For loops</title>
<title>For Loops</title>
<para>
Syntax:
<programlisting><![CDATA[for <identifier> = <from> to <to> do <body>
......@@ -1648,7 +1655,7 @@ Loop with identifier being set to all values from <literal>&lt;from&gt;</literal
</sect2>
<sect2 id="genius-gel-loops-foreach">
<title>Foreach loops</title>
<title>Foreach Loops</title>
<para>
Syntax:
<programlisting><![CDATA[for <identifier> in <matrix> do <body>]]></programlisting>
......@@ -1667,7 +1674,7 @@ will print out [1,2] and then [3,4].
</sect2>
<sect2 id="genius-gel-loops-break-continue">
<title>Break and continue</title>
<title>Break and Continue</title>
<para>
You can also use the <literal>break</literal> and <literal>continue</literal> commands in loops. The continue <literal>continue</literal> command will restart the current loop at its next iteration, while the <literal>break</literal> command exits the current loop.
<programlisting><![CDATA[while(<expression1>) do (
......@@ -1681,7 +1688,7 @@ You can also use the <literal>break</literal> and <literal>continue</literal> co
</sect1>
<sect1 id="genius-gel-sums-products">
<title>Sums and products</title>
<title>Sums and Products</title>
<para>
Syntax:
<programlisting><![CDATA[sum <identifier> = <from> to <to> do <body>
......@@ -1699,7 +1706,7 @@ If no body is executed (for example <userinput>sum i=1 to 0 do ...</userinput>)
</sect1>
<sect1 id="genius-gel-comparison-operators">
<title>Comparison operators</title>
<title>Comparison Operators</title>
<para>
The following standard comparison operators are supported in GEL and have the obvious meaning:
<literal>==</literal>, <literal>&gt;=</literal>,
......@@ -1748,7 +1755,7 @@ for conditional evaluation works here as well. For example, <literal>1 or a=1</l
</sect1>
<sect1 id="genius-gel-variables-global">
<title>Global variables and scope of variables</title>
<title>Global Variables and Scope of Variables</title>
<para>
Like most programming languages, GEL has two different types
of variables: local and global. A local variable only exists
......@@ -1923,17 +1930,68 @@ when you mean comparison.
<title>Advanced Programming with GEL</title>
<sect1 id="genius-gel-error-handling">
<title>Error handling</title>
<title>Error Handling