If you have used very old releases of TIGCC (prior to 0.9), you probably know that the use of floating point values and functions was possible, but only using some very awkward syntax, which caused a lot of headaches and nightmares. The TIGCC Team (mostly Sebastian Reichelt and Zeljko Juric) spent a lot of time and effort implementing native (ANSI) floats in TIGCC. And the results are now available: you can use regular floating point numbers and values now, as in all regular C compilers! This means that:
You can now use the standard ANSI types float
, double
and
long double
without any trouble (in fact, these three types are the same,
there is no difference between them). The old-style type ti_float
still exists due to compatibility reasons, but now it is the same as float
.
You can now use "standard" floating point constants (like 2.854). So, the following is now valid:
float a, b, c; a = 2.854; b = 7; c = 1.5e-7;
In other words, no more ugly FLT and FEXP macros! They still exist due to compatibility reasons, but their usage is very deprecated now.
You can now use standard arithmetic ('+', '-', '*', '/) and comparison ('<', '>', '<=', '>=', '==' and '!=') operators with floating point values. There is no need any more for the use of awkward functions like fadd, fcmp etc. So statements like these are now accepted:
p = (q + 3.15) / (q - r); x1 = (-b + sqrt (b * b - 4 * a * c)) / (2 * a); if (p < 3.0) q += 1e-3;
This feature is probably the best present for users...
You can use all floating point functions (like sqrt, sin etc.) as usual. In this release, a standard ANSI math library math.h is implemented, which contains nearly all functions proposed by ANSI C, with some extensions. The old timath.h library file still exists due to compatibility reasons, and it contains more functions than math.h, because it contains some functions for making compatibility with older programs, and some functions which are internally related to the TIOS. Anyway, you can do calculations like these:
a = sin (b); b = exp (1); c = log (3.19); a = sqrt (b + c) * sinh (a / 2.);
As you can see from the second example, automatic promotion from integer constants to the floating point is also implemented.
Integer types are now automatically promoted to floating point values when necessary, as
proposed in ANSI C. This means that the following constructions are valid, assuming that
'n'
is a variable of integer (short, long, signed, unsigned) type:
a = n; b = sqrt (n); c = b + n;
You can also explicitely cast an integer value to a floating point one:
a = (float)n;
The function flt which performs the promotion explicitely still exists, due to compatibility reasons.
Floating point types are automatically truncated to integers when the program expects an integer value (for example, when a floating point variable is assigned to an integer variable), as proposed in ANSI C. This means that you can write
n = a;
where 'n'
is an integer, and 'a'
is a float, although it is better
to express your wish more explicitely using type cast as
n = (int)a;
The function trunc which performs the truncation explicitely still exists due to compatibility reasons.
You can use printf and similar
functions to print floating point values, using the format specifiers %f
,
%e
and %g
, as defined in ANSI C. So, the following is
completely legal:
printf ("sin(%f)=%f", a, sin(a)); printf ("%f", 3.14);
Note that the second statement was not valid prior to release 0.9 of TIGCC!
To accept a floating point value from the keyboard, first accept it as a string (using gets, some user-written input routine, or functions from dialogs.h), then convert the string to a floating point value using the atof (ascii-to-float) function. To get a floating point argument passed from TI-Basic to the program, use the GetFloatArg function.
As you can see, the usage of floats is now essentially the same as in all other C compilers. See the description of the math.h and timath.h header files for more info. However, floating point support is not perfect yet. That's why there are still some limitations in the use of floating point values (fortunately, they are not serious):
The promotion of double long integers (long long types) to floating point values, and truncation of floating point values to longlongs are not implemented yet. If you try to do this (which is not very likely), you will get an "undefined reference" error during the linking stage.
As an example of usage of floating point values and functions, the program given below (called "Float Test") reads coefficients of a quadratic equation from the keyboard, then calculates and displays the solutions of the equation (including complex ones):
#define USE_TI89 #define USE_TI92PLUS #define USE_V200 #define SAVE_SCREEN #include <stdio.h> #include <math.h> #include <string.h> #include <kbd.h> void _main(void) { float a, b, c, d; char buffer[200]; clrscr (); puts ("a="); a = atof (gets (buffer)); puts ("b="); b = atof (gets (buffer)); puts ("c="); c = atof (gets (buffer)); if (is_nan (a) || is_nan (b) || is_nan (c)) return; d = b * b - 4. * a * c; if (d >= 0.) { float x1, x2; x1 = (-b + sqrt (d)) / (2. * a); x2 = (-b - sqrt (d)) / (2. * a); printf ("\nx1=%f\nx2=%f", x1, x2); } else { float re, im; re = -b / (2. * a); im = fabs (sqrt (-d) / (2. * a)); printf ("\nx1=%f-%f*i\nx2=%f+%f*i", re, im, re, im); } ngetchx(); }
See the description of the included header files for more info about the functions used.
As already mentioned above, the new floating point support is implemented while retaining
good compatibility with programs written with releases of TIGCC before 0.9
(read below to see possible reasons of incompatibility). So, the quadratic equation solver
given below, which is written using old methods, will still work with a new compiler.
Compare this (old-style) code with the previous (new-style) one to see how much clearer
the new-style code is...
#define SAVE_SCREEN #include <stdio.h> #include <timath.h> #include <string.h> #include <kbd.h> int _ti89, _ti92plus; void _main (void) { ti_float a, b, c, d; char buffer[200]; clrscr (); puts ("a="); a = atof (gets (buffer)); puts ("b="); b = atof (gets (buffer)); puts ("c="); c = atof (gets (buffer)); if (is_nan (a) || is_nan (b) || is_nan (c)) return; d = fsub (fmul (b, b), fmul (FLT (4), fmul (a, c))); if (fcmp (d, ZERO) >= 0) { ti_float x1, x2; x1 = fdiv (fadd (fneg (b), sqrt (d)), fadd (a, a)); x2 = fdiv (fsub (fneg (b), sqrt (d)), fadd (a, a)); printf ("\nx1=%f\nx2=%f", x1, x2); } else { ti_float re, im; re = fdiv (fneg (b), fadd (a,a)); im = fabs (fdiv (sqrt (fneg (d)), fadd(a, a))); printf ("\nx1=%f-%f*i\nx2=%f+%f*i", re, im, re, im); } ngetchx(); }
The possible reasons which may cause incompatibility (very unlikely) with programs written with very old versions of TIGCC (prior to 0.9) are:
The types ti_float and bcd
are not the same any more.
ti_float
is now equal to ANSI type float
, but
bcd
is still a structure. If your program uses the
bcd
type (not very likely), you should probably change it to
float
to make the program work, because functions which expect a
float
type will not accept a structured type. Two macros called
float_to_bcd and
bcd_to_float have been introduced to provide more general
conversion if necessary.
Functions fadd, fsub,
fmul, fdiv,
fneg, fcmp,
flt and trunc are not
absolutely equal to functions
bcdadd, bcdsub,
bcdmul, bcddiv,
bcdneg, bcdcmp,
bcdbcd and bcdlong any more.
The first group of functions now works with the ordinary float
type (and they
will continue to work with ti_float), but the second
group now only works with bcd structures. So, if you used
bcdadd
etc. in your program (not very likely), you should
probably change it to fadd
etc. to make the program work.
Suppose that your old program uses the ti_float type with direct access to its internal fields (not very likely), like in the following example:
ti_float a; a.exponent = 0x4003; a.mantissa = 0x3284300000000000;
Then the program will not work with the new compiler, because ti_float
is not a
structure any more. Using a new macro bcd_var you can easily
get your program to work. All you need to do is to re-express the above statements as
ti_float a; bcd_var(a).exponent = 0x4003; bcd_var(a).mantissa = 0x3284300000000000;
Note, however, that the bcd type is still a structure.