 |
» |
|
|
 |
Version A.06.20 of the HP aC++ compiler supports the following
new features: Decimal floating-point arithmetic (HP-UX 11.31 only)
(New) +O[no]autopar option now supported
in C++ mode and implies -mt (New) +inline_level num (Enhanced) +Oinlinebudget is deprecated In next release, default C compilation mode will change from C89 to C99 In next release, default C++ compilation mode changes to full -AA
Decimal floating-point arithmetic (HP-UX 11.31 only) (New) |  |
On HP-UX 11.31 systems, support is now included for decimal
floating-point arithmetic for C. This support follows the current
draft revision of the IEEE 754 floating-point standard and ISO/IEC
Technical Report 24732, Extensions for the
programming language C to support decimal floating-point arithmetic. With decimal FP (unlike the usual binary FP), typical numerical
strings can be represented exactly in the types, avoiding subtle
input errors and confusion from inexact output. Therefore, decimal
FP is WYSIWYG. Decimal FP is designed particularly for financial applications,
including banking, billing, tax calculation, currency exchange, and
accounting. A decimal FP representation is best thought of as a triple (s, c, q) composed of a sign (1 or −1), an integral coefficient, and a quantum exponent, representing s * c *10q. Therefore, 123. = (1, 123, 0) and 123.00 = (1, 12300, −2) are different representations,
although they have the same numerical value and compare equal. Arithmetic
operations are defined to preserve the position of the decimal point,
much as hand-computation would. For example, 123.00 + 45.6 = 168.60 and
123.00 * 0.01 = 1.2300. These special quantum semantics facilitate exact
fix-point calculation. For typical floating-point calculations, the
quantum semantics can be ignored. Decimal FP support includes the following:Three built-in decimal FP types: _Decimal32 _Decimal64 _Decimal128 |
with 7, 16, and 34 decimal digits of precision, respectively. The usual built-in arithmetic operators for decimal
FP operands: +, −, *, /, assignments, comparisons, and
conversions with integer and binary FP types, all with correctly-rounded
IEEE arithmetic. An operation may combine a decimal FP operand with
an operand of a different decimal FP type or with an integer type.
However, mixing operands of decimal and binary FP types is not allowed.
60 math functions for each decimal FP type. Function
suffixes are d32 for _Decimal32, d64 for _Decimal64, and d128 for _Decimal128. Included
are: Decimal FP versions of the C99 math functions. New functions to manage quantum exponents (for fixed-point
calculation). Routines to encode and decode data for either of the
two standard encodings for decimal FP data. Details of the encodings
are in the draft revision of IEEE 754, which refers to them as the
"binary encoding", which the HP C/aC++ compiler uses, and the "decimal
encoding". Both encodings provide exactly the same data, analogous
to big endian and little endian encodings.
Decimal FP I/O and string conversion. The decimal
FP length modifiers for printf()() and scanf()() floating-point conversion specifiers (a, A, e,
E, f, F, g, G) are H for _Decimal32, D for _Decimal64, and DD for _Decimal128. The decimal
a, A specifiers for printf()(), given no precision
or sufficient precision, produce an exact quantum-preserving representation
of the decimal FP value being converted. WDB debugger support for printing values of decimal
FP types. Suffixes to designate decimal floating constants: df or DF for _Decimal32, dd or DD for _Decimal64, and dl or DL for _Decimal128. Note that an unsuffixed floating constant
still has type double, regardless of the context. Explicit suffixing
with a d or D to specify type double
is also allowed. Decimal FP versions of macros in <float.h>, <math.h>, and <fenv.h>. Five rounding modes for decimal FP: to nearest with
ties to even, to nearest with ties away from zero, upward, downward,
and toward zero. Compiler option +decfp, which enables
full decimal FP functionality according to the ISO/IEC C draft Technical
Report: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1312.pdf Compiler option -fpevaldec=precision, which specifies the minimum precision to use for decimal
floating-point expression evaluation. The possible values for precision are _Decimal32, _Decimal64, and _Decimal128. This option does not affect the
precision of parameters, return types, or assignments. The default
is -fpevaldec=_Decimal32. Type-generic functions in <tgmath.h> that take on the type of decimal FP (or binary FP) arguments. Our Decimal FP support incorporates code from the
Intel Decimal Floating-Point Math Library.
Install the following on an HP-UX 11i V3 (11.31)
Integrity system: core Math patch PHSS_38137 math manpage patch PHCO_38388 libc man page patch PHCO_37128 (for printf and scanf
man pages)
To use any decimal FP functionality (even built-in
operators), add the +decfp option to the compile
and link lines. To use the decimal FP functionality in <math.h>, <float.h>, <fenv.h>, or <tgmath.h>, define __STDC_WANT_DEC_FP__
before including the header. To use strtod32(), strtod64(), or strtod128(), include <strtodec.h>. (These interfaces are not declared in <stdlib.h>, as specified in the ISO/IEC C draft Technical Report.) Also see the “HP-UX floating-point guide for
HP Integrity servers” at http://www.hp.com/go/fp.
Decimal Floating-Point Example |
/***********************************************************************
*
* This program is intended to illustrate how C decimal FP might be
* used in a commercial billing program.
*
* The program reads input data from a file, interprets each datum
* as a number of service minutes, converts to hours (rounding up to
* the nearest tenth of an hour), and multiplies by a billing rate
* (rounding to the nearest cent with halfway cases rounding away
* from zero). For each inputl, the program writes the billing amount
* as an ASCII character string to a file. Along the way, it
* accumulates sums of service minutes, hours billed, and amounts
* billed, and at the end writes the total sums to stdout.
*
* Program constants determine the input and output filenames and
* whether the input is ASCII, BID ("binary" encoding for decimal FP),
* or DPD ("decimal" encoding for decimal FP). The HP-UX
* implementation uses BID encoding for its decimal FP types.
*
**********************************************************************/
const char * ifilename = "biller.in"; // input file
const char * ofilename = "biller.out"; // output file
const enum { ascii, bid, dpd } encoding = ascii; // input encoding
const _Decimal64 rate = 149.95DD; // hourly billing rate
#define __STDC_WANT_DEC_FP__
#include <stdio.h>
#include <std.lib.h>
#include <math.h>
#include <fenv.h>
#include <strtodec.h>
#include <assert.h>
#pragma STDC FENV_ACCESS ON
int main() {
unsigned int n; // number of inputs
_Decimal64 m; // number of minutes
_Decimal64 h; // number of hours
_Decimal64 b; // amount billed
_Decimal64 sumM, sumH, sumB; // sums
const _Decimal64 onert = 0.0DD; // for rounding to tenths
const _Decimal64 twort = 0.00DD; // for rounding to hundredths
FILE *inp=NULL; // input stream
FILE *outp=NULL; // output stream
int r, s; // fread, scanf returns
_Binaryencoding64 be; // for binary-encoded (bid) input
_Decimalencoding64 de; // for decimal-encoded (dpd) input
// open input file
if (encoding == ascii)
inp = fopen(ifilename, "r");
else
inp = fopen(ifilename, "rb");
if (inp == NULL) {
fprintf(stderr, "FAILURE: could not open %s\n", ifilename);
exit(EXIT_FAILURE);
}
// open output file
outp = fopen(ofilename, "w");
if (outp == NULL) {
fprintf(stderr, "FAILURE: could not open %s\n", ofilename);
exit(EXIT_FAILURE);
}
// initialize sums
sumM = 0.DD;
sumH = 0.0DD;
sumB = 0.00DD;
// main loop
for (n=0; ; n++) {
// read a number
if (encoding == ascii) {
s = fscanf(inp, "%De", &m);
if (s == 0) {
fprintf(stderr, "FAILURE: on input from %s\n", ifilename);
fclose(inp);
fclose(outp);
exit(EXIT_FAILURE);
}
if (s == EOF) break;
}
else if (encoding == bid) {
r = (int) fread(&be, sizeof(_Binaryencoding64), 1, inp);
if (r != 1) break;
m = _decodebinary64(be); // decode bid
}
else /* encoding == dpd */ {
r = (int) fread(&de, sizeof(_Decimalencoding64), 1, inp);
if (r != 1) break;
m = _decodedecimal64(de); // decode dpd
}
// compute hours billed
fe_dec_setround(FE_DEC_UPWARD);
h = m / 60;
h = quantized64(h, onert); // round to tenths
// compute billing amount
fe_dec_setround(FE_DEC_TONEARESTFROMZERO);
b = rate * h;
b = quantized64(b, twort); // round to hundredths
// restore decimal rounding mode to default
fe_dec_setround(FE_DEC_TONEAREST);
// print billing amount to file
fprintf(outp, "%Da\n", b);
// update sums
sumM += m;
sumH += h;
sumB += b;
} // main loop
// close files
fclose(inp);
fclose(outp);
// confirm expected quantum in sums
assert(samequantumd64(sumH, onert));
assert(samequantumd64(sumB, twort));
// print summary
printf("SUMMARY:\n");
printf(" number of calls = %d\n", n);
printf(" total minutes = %Da\n", sumM);
printf(" total hours billed = %Da\n", sumH);
printf(" total amount billed = %Da\n", sumB);
return 0;
}
|
 |
Notes: The quantize functions do the work of rounding to
the desired number of places to the right of the decimal point. They
return the value of their first argument represented with the quantum
exponent of their second argument, rounding if necessary. Mixing decimal FP and integer operands, as in the
expression m / 60, is allowed.
However, the expression m / 60.0,
which mixes decimal and binary FP, would cause an error. On the HP-UX implementation, BID data could be read
directly into the decimal FP variable m, without the need of decoding. However, that code would not be portable
to systems that use DPD encoding for their decimal FP types. Restoring the default rounding has no effect in this
program, except perhaps if the ASCII input had more than 16 decimal
digits, but doing so is a good programming practice.
+annotate=structs (New) |  |
The +annotate=structs option annotates the
compiled binary with accesses to C/C++ struct fields
for use by other external tools such as Caliper. By default, no annotations
are added. +check=lock (New) |  |
The new runtime +check=lock option enables
the checking of locking discipline violations; for example, whether
appropriate locks are held when threads access shared data in applications
using Posix threads. Refer to the online programmer's guide for additional
detail and code example. Note that +check=lock is
not enabled by +check=all. +check=thread (New) |  |
The new runtime +check=thread option enables
the batch-mode thread-debugging features of HP WDB. This feature requires
HP WDB 5.9 or later. The following thread-related conditions can
be detected with +check=thread: The thread attempts to acquire a nonrecursive mutex
that it currently holds. The thread attempts to unlock a mutex or a read-write
lock that it has not acquired. The thread waits (blocked) on a mutex or read-write
lock that is held by a thread with a different scheduling policy. Different threads non-concurrently wait on the same
condition variable, but with different associated mutexes. The threads terminate execution without unlocking
the associated mutexes or read-write locks. The thread waits on a condition variable for which
the associated mutex is not locked. The thread terminates execution, and the resources
associated with the terminated thread continue to exist in the application
because the thread has not been joined or detached. The thread uses more than the specified percentage
of the stack allocated to the thread.
The +check=thread option should only be used
with multithreaded programs. It is not enabled by +check=all. +O[no]autopar now supported in C++ Mode (New) |  |
The +O[no]autopar option introduced in version
A.06.15 of the compiler was supported only when compiling C or Fortran
files. Version A.06.20 also supports this option when compiling C++
files. In addition, specifying +Oautopar now implies
the -mt option. +O[no]dynopt (HP-UX 11.31 only) (New) |  |
On HP-UX 11.31 systems, the +O[no]dynopt option
enables [disables] dynamic optimization for the output file. Both
forms of this option change the default setting, which allows the
run-time environment to enable or disable dynamic optimization according
to a system-wide default. This option applies only to executable files
and shared libraries, if the run-time environment supports this feature. chatr(1) can be used to change this setting, including
restoration of the default setting, after the output file has been
created. +inline_level num (Enhanced) |  |
The format for num is now N[.n],
where num is either an integral
value from 0 to 9 or a value with a single decimal place from 0.0
to 9.0, as follows: 0 No inlining is done (same effect as
the +d option). 1 Only functions marked with the inline keyword
or implied by the language to be inlined are considered for inlining. 1.0 < num <
2.0 Increasingly make inliner more aggressive below 2.0. 2 More inlining than level 1. This is the default
level at optimization levels +O2, +O3, and +O4. 2.0 < num <
9.0 Increasing levels of inliner aggressiveness. 9 Attempt to inline all functions other than recursive
functions or those with a variable number of arguments.
-dumpversion (New) |  |
The -dumpversion option displays the simple
version number of the compiler, such as A.06.20. Compare with the
-V option, which displays more verbose version information. #include_next (New) |  |
The #include_next preprocessor directive is
similar to the #include directive, but tells the
preprocessor to continue the include-file search beyond the current
directory, and include the subsequent instance found in the file-search
path. #pragma diag_push (New) |  |
This scoped pragma saves the current severity state of all diagnostics.
Subsequent uses of pragmas that modify the severity of a given diagnostic
will be in effect within the scope of the diag_push pragma. The effective scope ends with a corresponding #pragma
diag_pop. You can specify a #pragma diag_push within the scope of another #pragma diag_push,
which results in a new saved severity state and a new effective scope.
A compilation unit should have an equal number of #pragma
diag_push and #pragma diag_pop uses. #pragma diag_pop (New) |  |
This pragma restores the severities of all diagnostics to the
state prior to the last #pragma diag_push. A compilation
unit should have an equal number of #pragma diag_push and #pragma diag_pop uses. +Oinlinebudget is deprecated (Change) |  |
The +Oinlinebudget option is deprecated in
this release and will not be supported in future releases. Use +inline_level. In next release, default C compilation mode will change from
C89 to C99 |  |
In the next version of the HP C/aC++ compiler, the default C
compilation mode will change from c89 to c99. So cc -Ae or aCC -Ae will be the same as -AC99, and C99 features will be enabled. Users can prepare for this transition by adding -AC99 to their build options and addressing any issues. Errors that can
happen with -AC99 include: enum out of range: error #2066: enumeration value is out of "int" range
error #4041: enumeration value is out of "char" range |
Restriction on constant expressions: error #2057: this operator is not allowed in a constant expression
error #2028: expression must have a constant value
Was this:
warning #4045-D: non-constant initialization performed at runtime |
Non-static inline can't reference static: error #3031-D: an entity with internal linkage cannot be referenced
within an inline function with external linkage |
Use of inline or restrict as variables/functions/types. New diagnostics will be added to
warn users about the use of inline and restrict in this release (A.06.20). For example: 4347 %s is a keyword in the C99 C Standard, and its usage as an
identifier will cause an error in C99 mode |
In next release, default C++ compilation mode will change to
full -AA |  |
In the next version of the HP C/aC++ compiler, the default C++
compilation mode will change from almost -AA to -AA. This will enable -Wc,-ansi_for_scope,on. This is being done to reduce porting efforts by meeting the C++
Standard. Users can prepare for this transition by adding -AA to their build options and addressing any issues. Errors and warnings
(with unintended runtime results) that can happen with -Wc,-ansi_for_scope,on include: Loop index is no longer in scope after the for loop
body: error #2020: identifier "i" is undefined |
Reference to outer scope variable instead of loop
index: warning #2780-D: reference is to variable "i" (declared at line X) --
under old for-init scoping rules it would have been variable "i"
(declared at line Y)
With +wlint:
warning #3348-D: declaration hides variable "i" (declared at line X) |
By also compiling with +We2780, the two errors,
2020 and 2780, should catch any issues resulting from the change
in the C++ default. If you are already using -Aa, this also enables
the new default.
|