Skip to content

Floating-point math (math.h)

Include math.h. The DCC C Compiler has only 32-bit float (no double), so the math entry points are the single-precision ...f variants. The unsuffixed C89 names are provided as macro aliases for convenience.

Standard C names

The standard C89 math names are provided as function-like macros that call the corresponding single-precision ...f runtime function.

Name Meaning
acos Single-precision alias for acosf.
asin Single-precision alias for asinf.
atan Single-precision alias for atanf.
atan2 Single-precision alias for atan2f.
ceil Single-precision alias for ceilf.
cos Single-precision alias for cosf.
cosh Single-precision alias for coshf.
dcc_nan IEEE-754 quiet NaN. Unlike INFINITY, this has no spelling as a numeric literal token, so it is a real extern float object (defined in DCCRTL.MAC) rather than a constant expression: usable in ordinary expressions and local initializers, but NOT in a static/global initializer.
exp Single-precision alias for expf.
fabs Single-precision alias for fabsf.
floor Single-precision alias for floorf.
fmod Single-precision alias for fmodf.
frexp Single-precision alias for frexpf.
HUGE_VAL Value returned on overflow; equals FLT_MAX (dcc has no double).
HUGE_VALF C99 float-flavored HUGE_VAL; true IEEE-754 infinity, unlike HUGE_VAL.
INFINITY IEEE-754 positive infinity, as a genuine compile-time constant: dcc's float-literal parser hands the source text to the host's atof(), and 1e40 already exceeds FLT_MAX, so the host overflows it to (double) infinity before it's narrowed to float. No runtime code, no RTL linkage; usable anywhere a float constant expression is, including static initializers.
ldexp Single-precision alias for ldexpf.
log Single-precision alias for logf.
log10 Single-precision alias for log10f.
modf Single-precision alias for modff.
pow Single-precision alias for powf.
sin Single-precision alias for sinf.
sinh Single-precision alias for sinhf.
sqrt Single-precision alias for sqrtf.
tan Single-precision alias for tanf.
tanh Single-precision alias for tanhf.

Functions

Function Summary
float acosf(float x) Arc cosine of x.
float asinf(float x) Arc sine of x.
float atan2f(float y, float x) Arc tangent of y / x using the signs of both arguments.
float atanf(float x) Arc tangent of x.
float ceilf(float x) Round toward positive infinity.
float cosf(float x) Cosine of x, in radians.
float coshf(float x) Hyperbolic cosine.
float expf(float x) Base-e exponential, e raised to x.
float fabsf(float x) Absolute value.
float floorf(float x) Round toward negative infinity.
float fmodf(float x, float y) Floating-point remainder of x / y.
float frexpf(float x, int *eptr) Split x into a normalized fraction and exponent.
int isfinite(float x) True if x is neither NaN nor +/-Inf.
int isinf(float x) True if x is +Inf or -Inf.
int isnan(float x) True if x is a NaN (quiet or signaling).
float ldexpf(float x, int n) Compute x multiplied by 2 raised to n.
float log10f(float x) Base-10 logarithm.
float logf(float x) Natural logarithm, base e.
float modff(float x, float *iptr) Split x into integer and fractional parts.
float nextafterf(float x, float y) Next representable value after x in the direction of y.
float powf(float x, float y) x raised to the power y.
int signbit(float x) True if x's sign bit is set (negative, including -0.0 and -NaN).
float sinf(float x) Sine of x, in radians.
float sinhf(float x) Hyperbolic sine.
float sqrtf(float x) Square root.
float tanf(float x) Tangent of x, in radians.
float tanhf(float x) Hyperbolic tangent.

Runtime model

DCC C Compiler treats float as the only floating type. C89 normally declares the unsuffixed math names (sqrt, sin, pow, and so on) as double functions, but this runtime has no double, so math.h maps those names to the single-precision ...f functions with macros.

Float is the biggest size lever

A single float operator links the shared normalise/round core, and the transcendental functions (expf/logf/powf and the trig/hyperbolic families) are the heaviest individual features in the runtime. They are software routines on the Z80, not hardware floating-point operations, so budget both code size and execution time. See the appendix.

Function groups

The functions follow the conventional C math families, with single-precision types throughout:

  • Rounding, remainder, and roots: fabsf, floorf, ceilf, fmodf, sqrtf, nextafterf.
  • Exponential and logarithmic: expf, logf, log10f, powf.
  • Trigonometric: sinf, cosf, tanf, asinf, acosf, atanf, atan2f.
  • Hyperbolic: sinhf, coshf, tanhf.
  • Decomposition: frexpf, ldexpf, modff.

For portable C89 source, the unsuffixed aliases let familiar calls use the same single-precision runtime functions. For example, sqrt(x) expands to sqrtf(x), and atan2(y, x) expands to atan2f((y), (x)).

#include <math.h>

float distance(float dx, float dy)
{
  return sqrtf(dx * dx + dy * dy);
}

float heading(float y, float x)
{
  return atan2f(y, x);
}

Printing floats

Use %f to print a float. dcc detects literal formats automatically:

float r = sqrtf(2.0f);
printf("%f\n", r);

The -ffloatio option forces %f support on every printf-family call; it is not required for a literal format and does not add floating-point scanf input. Float output is supported by printf, sprintf, fprintf, their v... forms, snprintf, and vsnprintf. See Console and file I/O for the full formatted I/O subset.

Accuracy

The transcendental routines (expf/logf/powf, the trig and hyperbolic families) are single-precision polynomial and series approximations: expect roughly 5-6 significant digits on ordinary ranges, not full float round-trip accuracy. The range-reduction in sinf/cosf/tanf uses fmodf, so accuracy gradually degrades for very large arguments.

Precision and mixed-type gotchas

  • float carries about 7 decimal digits (a 24-bit significand). Integers up to 2^24 (16,777,216) are exact; beyond that only some integers are representable. (long)(float)16777217L is 16777216, not 16777217. The same rounding applies in constant expressions, case labels, and array bounds.
  • Comparing a wide integer against a float happens in float. The integer side converts first, so 16777216L < (float)16777217L is false (the cast rounded down to 16777216.0f). Compare as integers when you need full 32-bit precision.
  • Any float arm makes a ?: a float expression. cond ? 2 : 3.5f yields a float, not an int; cast the result if you need an integer.
  • A float is "true" when its magnitude is nonzero. if (f), f ? a : b, !f, f && g, and while (f) test against zero, and both +0.0f and -0.0f count as false.