Issue 1070: macros for fixed arithmetic results (cxx_revision) Source: (, ) Nature: Uncategorized Issue Severity: Summary: Summary: The fixed mapping says on page 20-35 of orbos/98-01-11: One way to do this is to declare the result types with a macro that evaluates to the approate values, based on the digits and scale of the operands: // Example of Fixed result type declaraction // Fixed<_FIXED_ADD_TYPE(d1,s1,d2,s2)> -> Fixed<dr,sr> I think the name of the macro for each rule needs to be nailed down. Resolution: Revised Text: Actions taken: March 18, 1998: received issue February 23, 1999: closed issue Discussion: End of Annotations:===== Return-Path: X-Authentication-Warning: tigger.dstc.edu.au: michi owned process doing -bs Date: Wed, 18 Mar 1998 17:52:13 +1000 (EST) From: Michi Henning To: issues@omg.org, cxx_revision@dstc.edu.au Subject: Macros for fixed arithmetic results Hi, The fixed mapping says on page 20-35 of orbos/98-01-11: One way to do this is to declare the result types with a macro that evaluates to the approate values, based on the digits and scale of the operands: // Example of Fixed result type declaraction // Fixed<_FIXED_ADD_TYPE(d1,s1,d2,s2)> -> Fixed I think the name of the macro for each rule needs to be nailed down. Consider: // C++ Fixed<3,2> f1 = ...; Fixed<6,3> f2 = ...; // Add f1 and f2. According to the rules on page 3-20, the result // type is Fixed<7,3> Fixed<7,3> f3 = f1 + f2; The problem is that to write the type of f3, I need to know and evaluate the rules on page 3-20 (not trivial). The macro takes the work away: Fixed<_FIXED_ADD_TYPE(3,2,6,3)> f3 = f1 + f2; If the macro is correctly defined, this evaluates to Fixed<7,3>. However, to do this, I need to know the macro *name*. I think the macro names for the four arithmetic operators should be standardized, otherwise I can't write portable code. Cheers, Michi. -- Michi Henning +61 7 33654310 DSTC Pty Ltd +61 7 33654311 (fax) University of Qld 4072 michi@dstc.edu.au AUSTRALIA http://www.dstc.edu.au/BDU/staff/michi-henning.html Return-Path: Sender: jon@floorboard.com Date: Mon, 20 Jul 1998 12:02:08 -0700 From: Jonathan Biggar To: cxx_revision@omg.org Subject: Proposal to "fix" fixed point in the C++ mapping :-) This proposal addresses the following issues: Issue 1056: Fixed types in orbos/98-01-11 Issue 1069: Typos on p 20-34 of orbos/98-01-11 Issue 1070: macros for fixed arithmetic results * Issue 1072: fixed_digits and fixed_scale member functions Issue 1073: Missing constructor for Fixed Issue 1092: C++ mapping for fixed is broken (01) * Issue 1093: C++ mapping for fixed is broken (02) Issue 1124: C++ Fixed type issue (01) Issue 1125: Fixed type (02) Issue 1126: C++ Fixed Type (03) Issue 1538: Missing text describing fixed point constant mapping Summary description of the problems with fixed: The worst problem with the existing CORBA 2.2 mapping for fixed point types is the attempted use of a template type with the digits and scale as template arguments. This causes two major problems, neither of which is possible to fix without reworking the mapping entirely. The first is that the Fixed is defined as a template in the CORBA namespace. This cannot be implemented in a compiler that does not support either namespaces or member templates. Since there are still quite a few compilers with this deficiency, this is a bad idea for a fundamental type. The second problem is that the arithmetic for fixed point types (particularly the divide operation) defines the digits and scale of the result of binary mathematics operations (+, -, *, /) to depend on the runtime values of the arguments. This cannot be expressed using C++ template declarations, since the digits and scale must be compile time constants. The second problem area with the fixed point mapping is that the mapping totally ignores fixed point constant declarations and how to map them into C++. For an IDL fixed point declaration: const fixed foo = 1.2D; neither the use of the keyword "fixed" without digits and scale parameters, nor the actual fixed point literal, "1.2D" have a mapping into C++. The third major problem area has to do with the IDL grammar itself. The CORBA 2.2 grammar allows fixed point types to be defined anonymously (without a typedef) as IDL operation parameters or return types. But since the C++ mapping specifies that _var and _out types are defined for anonymous fixed point types, this causes two problems: first, the mapping does not define how to handle a negative scale when determining the name for the _var and _out types for an anonymous fixed point type, and second, there is no clear place to define the _var and _out types when an anonymous fixed point type is used as an IDL parameter or return type. Overview of the Proposal: The key to the proposal is to redefine CORBA::Fixed to be a non-template type that can handle any combination of digits and scale at run time. All of the arithmetic operations are defined using CORBA::Fixed. However, this proposal does not require that CORBA::Fixed be used as the type for operation parameters and fields in IDL structured types (struct, union, sequence, array, etc). The reason for this is that a generic fixed point value needs about 18 bytes of storage, minimum--16 for the 31 digits plus sign, 2 for the digits and scale values. So, by allowing the implementation to choose to use another type for fixed point types with an explicit digits and scale, this gives the implementation the flexibility to reduce the storage cost for fixed point types in places where the digits and scale are known. It also allows the implementation to code the bounds check for digits and scale into the conversion between the "generic" CORBA::Fixed type and the actual type used for operation parameters and structured members, rather than having to add code at runtime to check these bounds inside the marshaling engine. In fact, an implementation could still use a template for these unnamed types without the problems described above, since the implementation is free to declare the template however it needs to. The second problem, that the mapping for fixed point constants is not specified, is solved by mapping fixed point constants to normal C++ string literals. The third problem, issues with declaring _out & _var types for fixed point has been mainly resolved by the ORB core RTF, which has already approved a fix that obviate the need for the C++ RTF to fix these problems. The proposal accepted by the core RTF are to forbid the declaration of anonymous fixed types as IDL operation parameters. In addition, the proposal presented here eliminates the _var type for fixed point types, because it is unnecessary. This proposal just treats C++ fixed point types like built-in C++ types. Since a maximal sized fixed point type needs little if any more storage than a long double, which is passed by value, there isn't much need to use dynamic storage (new and delete) for fixed point values. Besides, the C++ mapping specifies that fixed point types are always passed by reference, and never by pointer. The ORB core RTF has also passed a proposal that outlaws the use of a negative scale, since the original CORBA 2.2 specification stated that this was not portable anyway. Proposal: Make the following changes to the CORBA 2.2 C++ mapping (section 20): -------------------------------------------------------------------------------- Add the following paragraphs to the end of section 20.4: Fixed Point Constants Since C++ does not have a native fixed point type, IDL fixed point literals are mapped to C++ strings without the trailing 'd' or 'D' in order to guarantee that there is no loss of precision. For example, the IDL fixed point literal 123.456D is mapped to the C++ string "123.456". -------------------------------------------------------------------------------- Replace the entire text of section 20.11 with: The C++ mapping for fixed is defined by the following class: class Fixed { public: // Constructors... Fixed(int val = 0); Fixed(long val); Fixed(unsigned val); Fixed(unsigned long val); Fixed(Double val); Fixed(LongDouble val); Fixed(const Fixed& val); ~Fixed(); // Conversions... operator LongDouble() const; Fixed round(UShort digits, UShort scale) const; Fixed truncate(UShort digits, UShort scale) const; // Operators... Fixed& operator=(const Fixed& val); Fixed& operator+=(const Fixed& val); Fixed& operator-=(const Fixed& val); Fixed& operator*=(const Fixed& val); Fixed& operator/=(const Fixed& val); Fixed& operator++(); Fixed& operator++(int); Fixed& operator--(); Fixed& operator--(int); Fixed& operator+() const; Fixed& operator-() const; int operator!() const; // Other member functions UShort fixed_digits() const; UShort fixed_scale() const; }; istream& operator>>(istream& is, Fixed &val); ostream& operator<<(ostream& os, const Fixed &val); Fixed operator + (const Fixed &val1, const Fixed &val2); Fixed operator - (const Fixed &val1, const Fixed &val2); Fixed operator * (const Fixed &val1, const Fixed &val2); Fixed operator / (const Fixed &val1, const Fixed &val2); Fixed operator > (const Fixed &val1, const FIxed &val2); Fixed operator < (const Fixed &val1, const FIxed &val2); Fixed operator >= (const Fixed &val1, const FIxed &val2); Fixed operator <= (const Fixed &val1, const FIxed &val2); Fixed operator == (const Fixed &val1, const FIxed &val2); Fixed operator != (const Fixed &val1, const FIxed &val2); -------------------------------------------------------------------------------- 20.16.2 -------------------------------------------------------------------------------- 20.16.3 -------------------------------------------------------------------------------- 20.39.4 -------------------------------------------------------------------------------- -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Sender: jon@floorboard.com Date: Mon, 20 Jul 1998 14:22:39 -0700 From: Jonathan Biggar To: cxx_revision@omg.org Subject: Proposal to "fix" fixed point in the C++ mapping :-) [Ok, here is the real version of the proposal. Jump in and comment as quickly as you can so that we can get this into a C++ RTF report in time for CORBA 2.3. You don't need to be gentle--I don't bite.] This proposal addresses the following issues: Issue 1056: Fixed types in orbos/98-01-11 Issue 1069: Typos on p 20-34 of orbos/98-01-11 Issue 1070: macros for fixed arithmetic results Issue 1072: fixed_digits and fixed_scale member functions Issue 1073: Missing constructor for Fixed Issue 1092: C++ mapping for fixed is broken (01) Issue 1093: C++ mapping for fixed is broken (02) Issue 1124: C++ Fixed type issue (01) Issue 1125: Fixed type (02) Issue 1126: C++ Fixed Type (03) Issue 1538: Missing text describing fixed point constant mapping Summary description of the problems with fixed: The worst problem with the existing CORBA 2.2 mapping for fixed point types is the attempted use of a template type with the digits and scale as template arguments. This causes two major problems, neither of which is possible to fix without reworking the mapping entirely. The first is that the Fixed is defined as a template in the CORBA namespace. This cannot be implemented in a compiler that does not support either namespaces or member templates. Since there are still quite a few compilers with this deficiency, this is a bad idea for a fundamental type. The second problem is that the arithmetic for fixed point types (particularly the divide operation) defines the digits and scale of the result of binary mathematics operations (+, -, *, /) to depend on the runtime values of the arguments. This cannot be expressed using C++ template declarations, since the digits and scale must be compile time constants. The second problem area with the fixed point mapping is that the mapping totally ignores fixed point constant declarations and how to map them into C++. For an IDL fixed point declaration: const fixed foo = 1.2D; neither the use of the keyword "fixed" without digits and scale parameters, nor the actual fixed point literal, "1.2D" have a mapping into C++. The third major problem area has to do with the IDL grammar itself. The CORBA 2.2 grammar allows fixed point types to be defined anonymously (without a typedef) as IDL operation parameters or return types. But since the C++ mapping specifies that _var and _out types are defined for anonymous fixed point types, this causes two problems: first, the mapping does not define how to handle a negative scale when determining the name for the _var and _out types for an anonymous fixed point type, and second, there is no clear place to define the _var and _out types when an anonymous fixed point type is used as an IDL parameter or return type. Overview of the Proposal: The key to the proposal is to redefine CORBA::Fixed to be a non-template type that can handle any combination of digits and scale at run time. All of the arithmetic operations are defined using CORBA::Fixed. However, this proposal does not require that CORBA::Fixed be used as the type for operation parameters and fields in IDL structured types (struct, union, sequence, array, etc). The reason for this is that a generic fixed point value needs about 18 bytes of storage, minimum--16 for the 31 digits plus sign, 2 for the digits and scale values. So, by allowing the implementation to choose to use another type for fixed point types with an explicit digits and scale, this gives the implementation the flexibility to reduce the storage cost for fixed point types in places where the digits and scale are known. It also allows the implementation to code the bounds check for digits and scale into the conversion between the "generic" CORBA::Fixed type and the actual type used for operation parameters and structured members, rather than having to add code at runtime to check these bounds inside the marshaling engine. In fact, an implementation could still use a template for these unnamed types without the problems described above, since the implementation is free to declare the template however it needs to. The second problem, that the mapping for fixed point constants is not specified, is solved by mapping fixed point constants to normal C++ string literals. The third problem, issues with declaring _out & _var types for fixed point has been mainly resolved by the ORB core RTF, which has already approved a fix that obviate the need for the C++ RTF to fix these problems. The proposal accepted by the core RTF are to forbid the declaration of anonymous fixed types as IDL operation parameters. In addition, the proposal presented here eliminates the _var type for fixed point types, because it is unnecessary. This proposal just treats C++ fixed point types like built-in C++ types. Since a maximal sized fixed point type needs little if any more storage than a long double, which is passed by value, there isn't much need to use dynamic storage (new and delete) for fixed point values. Besides, the C++ mapping specifies that fixed point types are always passed by reference, and never by pointer. The ORB core RTF has also passed a proposal that outlaws the use of a negative scale, since the original CORBA 2.2 specification stated that this was not portable anyway. Proposal: Make the following changes to the CORBA 2.2 C++ mapping (section 20): -------------------------------------------------------------------------------- Add the following paragraphs to the end of section 20.4: Fixed Point Constants Since C++ does not have a native fixed point type, IDL fixed point literals are mapped to C++ strings without the trailing 'd' or 'D' in order to guarantee that there is no loss of precision. For example, the IDL fixed point literal 123.456D is mapped to the C++ string "123.456". -------------------------------------------------------------------------------- Replace the entire text of section 20.11 with: 20.11 Mapping for Fixed The C++ mapping for fixed is defined by the following class: class Fixed { public: // Constructors... Fixed(int val = 0); Fixed(unsigned val); Fixed(Long val); Fixed(ULong val); Fixed(LongLong val); Fixed(ULongLong val); Fixed(Double val); Fixed(LongDouble val); Fixed(const Fixed& val); Fixed(const char *); ~Fixed(); // Conversions... operator LongLong() const; operator LongDouble() const; Fixed round(UShort digits, UShort scale) const; Fixed truncate(UShort digits, UShort scale) const; char *to_string(); // Operators... Fixed& operator=(const Fixed& val); Fixed& operator+=(const Fixed& val); Fixed& operator-=(const Fixed& val); Fixed& operator*=(const Fixed& val); Fixed& operator/=(const Fixed& val); Fixed& operator++(); Fixed& operator++(int); Fixed& operator--(); Fixed& operator--(int); Fixed& operator+() const; Fixed& operator-() const; int operator!() const; // Other member functions UShort fixed_digits() const; UShort fixed_scale() const; }; istream& operator>>(istream& is, Fixed &val); ostream& operator<<(ostream& os, const Fixed &val); Fixed operator + (const Fixed &val1, const Fixed &val2); Fixed operator - (const Fixed &val1, const Fixed &val2); Fixed operator * (const Fixed &val1, const Fixed &val2); Fixed operator / (const Fixed &val1, const Fixed &val2); Fixed operator > (const Fixed &val1, const Fixed &val2); Fixed operator < (const Fixed &val1, const Fixed &val2); Fixed operator >= (const Fixed &val1, const Fixed &val2); Fixed operator <= (const Fixed &val1, const Fixed &val2); Fixed operator == (const Fixed &val1, const Fixed &val2); Fixed operator != (const Fixed &val1, const Fixed &val2); The Fixed class is used directly by the C++ mapping for IDL fixed point constant values and for all intermediate results of arithmetic operations on fixed point values. For fixed point parameters of IDL operations or members of IDL structured datatypes, the implementation may use the Fixed type directly, or alternatively, may use a different type, with an effectively constant digits and scale, that provides the same C++ interface and can be implicitly converted from/to the Fixed class. The name(s) of this alternative class is not defined by this mapping. Since fixed point types used as parameters of IDL operations must be named via an IDL typedef declaration, the mapping must use the typedef to define the type of the operation parameter to make sure that server side operation signatures are portable. The Fixed class has a number of constructors to guarantee that a fixed value can be constructed from any of the IDL standard integer and floating point types. The Fixed(char *) constructor converts a string representation of a fixed point literal into a real fixed point value, with the trailing 'd' or 'D' optional. The Fixed class also provides conversion operators back to the LongLong and LongDouble types. The to_string() function provides an explicit conversion of a fixed point value to a string representation without the trailing 'd' or 'D'. The returned string value must be released by the caller using CORBA::string_free(). The round() and truncate() functions convert a fixed value to a new value with the specified digits and scale. If the new digits and scale require the value to loose precision on the right, the round() function will round away from zero values that are halfway or more to the next absolute value for the new fixed precision. The truncate() function always truncates the value towards zero. So, for example: Fixed f1 = "0.1"; Fixed f2 = "0.05"; Fixed f3 = "-0.005; f1.round(1,0) and f1.truncate(1,0) both return 0., f2.round(2,1) returns 0.1, f2.truncate(2,1) returns 0.0, f3.round(3,2) returns -0.01 and f3.truncate returns 0.00. The fixed_digits() and fixed_scale() functions return the smallest digits and scale value that can hold the complete fixed point value. If the implementation uses alternative classes for operation parameters and structured type members, then fixed_digits() and fixed_scale() return the constant digits and scale values defined by the source IDL fixed point type. Arithmetic operations on the Fixed class must calculate the result exactly, using an effective double precision (62 digit) temporary value. The results are then truncated at run time to fit in a maximum of 31 digits using the method defined in 3.7.2 to determine the new digits and scale. If the result of any arithmetic operation produces more than 31 digits to the left of the decimal point, the DATA_CONVERSION exception will be thrown. If a fixed point value, used as an actual operation parameter or assigned to a member of an IDL structured datatype, exceeds the maximum absolute value implied by the digits and scale, the DATA_CONVERSION exception will be thrown. The stream insertion and extraction operators << and >> convert a fixed point value to/from a stream using the format defined for an IDL fixed point literal. For stream insertion, the trailing 'd' or 'D' is left off, and for stream insertion, the 'd' or 'D' is optional. 20.11.1 Fixed T_var and T_out Types Since fixed point types are always passed by reference as operation parameters and returned by value, there is no need for a _var type for fixed point. For each IDL fixed point typedef a corresponding _out type is defined as a reference to the fixed point type: // IDL typedef fixed<5,2> F; // C++ typedef Implementation_Defined_name F; typedef F &F_out; -------------------------------------------------------------------------------- In section 20.16.2, add the following bullet to the first bullet list: o Fixed types and change the following paragraph to: For values of type T that are too large to be passed by value efficiently, such as structs, unions, sequences, Any, and exceptions, two forms of the insertion function are provided. -------------------------------------------------------------------------------- In section 20.16.3, add the following bullet to the first bullet list: o Fixed types and change the paragraph that reads: "For non-primitive types, such as struct, union, sequence, exception, Any, and fixed types, extraction is done by pointer. For example, consider the following IDL struct:" to: For non-primitive types, such as struct, union, sequence, exception, and Any, extraction is done by pointer. For example, consider the following IDL struct: -------------------------------------------------------------------------------- In section 20.39.4 add the following member functions to the Any class right after the corresponding Double operations: void operator<<=(const Fixed &); void operator>>=(Fixed &); -------------------------------------------------------------------------------- Change the fixed point type row in Table 20-2 to: fixed const Fixed & Fixed & Fixed & Fixed -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Sender: jon@floorboard.com Date: Tue, 21 Jul 1998 08:07:14 -0700 From: Jonathan Biggar To: cxx_revision@omg.org Subject: Version 2 of proposal to "fix" fixed point in the C++ mapping :-) [Here is version 2 of the proposal. I realized last night that inserting and extracting fixed point to/from an any required from_fixed & to_fixed classes to specify the digits and scale that should be embedded in the TypeCode. So the parts dealing with any have been rewritten.] This proposal addresses the following issues: Issue 1056: Fixed types in orbos/98-01-11 Issue 1069: Typos on p 20-34 of orbos/98-01-11 Issue 1070: macros for fixed arithmetic results Issue 1072: fixed_digits and fixed_scale member functions Issue 1073: Missing constructor for Fixed Issue 1092: C++ mapping for fixed is broken (01) Issue 1093: C++ mapping for fixed is broken (02) Issue 1124: C++ Fixed type issue (01) Issue 1125: Fixed type (02) Issue 1126: C++ Fixed Type (03) Issue 1538: Missing text describing fixed point constant mapping Summary description of the problems with fixed: The worst problem with the existing CORBA 2.2 mapping for fixed point types is the attempted use of a template type with the digits and scale as template arguments. This causes two major problems, neither of which is possible to fix without reworking the mapping entirely. The first is that the Fixed is defined as a template in the CORBA namespace. This cannot be implemented in a compiler that does not support either namespaces or member templates. Since there are still quite a few compilers with this deficiency, this is a bad idea for a fundamental type. The second problem is that the arithmetic for fixed point types (particularly the divide operation) defines the digits and scale of the result of binary mathematics operations (+, -, *, /) to depend on the runtime values of the arguments. This cannot be expressed using C++ template declarations, since the digits and scale must be compile time constants. The second problem area with the fixed point mapping is that the mapping totally ignores fixed point constant declarations and how to map them into C++. For an IDL fixed point declaration: const fixed foo = 1.2D; neither the use of the keyword "fixed" without digits and scale parameters, nor the actual fixed point literal, "1.2D" have a mapping into C++. The third major problem area has to do with the IDL grammar itself. The CORBA 2.2 grammar allows fixed point types to be defined anonymously (without a typedef) as IDL operation parameters or return types. But since the C++ mapping specifies that _var and _out types are defined for anonymous fixed point types, this causes two problems: first, the mapping does not define how to handle a negative scale when determining the name for the _var and _out types for an anonymous fixed point type, and second, there is no clear place to define the _var and _out types when an anonymous fixed point type is used as an IDL parameter or return type. Overview of the Proposal: The key to the proposal is to redefine CORBA::Fixed to be a non-template type that can handle any combination of digits and scale at run time. All of the arithmetic operations are defined using CORBA::Fixed. However, this proposal does not require that CORBA::Fixed be used as the type for operation parameters and fields in IDL structured types (struct, union, sequence, array, etc). The reason for this is that a generic fixed point value needs about 18 bytes of storage, minimum--16 for the 31 digits plus sign, 2 for the digits and scale values. So, by allowing the implementation to choose to use another type for fixed point types with an explicit digits and scale, this gives the implementation the flexibility to reduce the storage cost for fixed point types in places where the digits and scale are known. It also allows the implementation to code the bounds check for digits and scale into the conversion between the "generic" CORBA::Fixed type and the actual type used for operation parameters and structured members, rather than having to add code at runtime to check these bounds inside the marshaling engine. In fact, an implementation could still use a template for these unnamed types without the problems described above, since the implementation is free to declare the template however it needs to. The second problem, that the mapping for fixed point constants is not specified, is solved by mapping fixed point constants to normal C++ string literals. The third problem, issues with declaring _out & _var types for fixed point has been mainly resolved by the ORB core RTF, which has already approved a fix that obviate the need for the C++ RTF to fix these problems. The proposal accepted by the core RTF are to forbid the declaration of anonymous fixed types as IDL operation parameters. In addition, the proposal presented here eliminates the _var type for fixed point types, because it is unnecessary. This proposal just treats C++ fixed point types like built-in C++ types. Since a maximal sized fixed point type needs little if any more storage than a long double, which is passed by value, there isn't much need to use dynamic storage (new and delete) for fixed point values. Besides, the C++ mapping specifies that fixed point types are always passed by reference, and never by pointer. The ORB core RTF has also passed a proposal that outlaws the use of a negative scale, since the original CORBA 2.2 specification stated that this was not portable anyway. Proposal: Make the following changes to the CORBA 2.2 C++ mapping (section 20): -------------------------------------------------------------------------------- Add the following paragraphs to the end of section 20.4: Fixed Point Constants Since C++ does not have a native fixed point type, IDL fixed point literals are mapped to C++ strings without the trailing 'd' or 'D' in order to guarantee that there is no loss of precision. For example, the IDL fixed point literal 123.456D is mapped to the C++ string "123.456". -------------------------------------------------------------------------------- Replace the entire text of section 20.11 with: 20.11 Mapping for Fixed The C++ mapping for fixed is defined by the following class: class Fixed { public: // Constructors... Fixed(int val = 0); Fixed(unsigned val); Fixed(Long val); Fixed(ULong val); Fixed(LongLong val); Fixed(ULongLong val); Fixed(Double val); Fixed(LongDouble val); Fixed(const Fixed& val); Fixed(const char *); ~Fixed(); // Conversions... operator LongLong() const; operator LongDouble() const; Fixed round(UShort digits, UShort scale) const; Fixed truncate(UShort digits, UShort scale) const; char *to_string(); // Operators... Fixed& operator=(const Fixed& val); Fixed& operator+=(const Fixed& val); Fixed& operator-=(const Fixed& val); Fixed& operator*=(const Fixed& val); Fixed& operator/=(const Fixed& val); Fixed& operator++(); Fixed& operator++(int); Fixed& operator--(); Fixed& operator--(int); Fixed& operator+() const; Fixed& operator-() const; int operator!() const; // Other member functions UShort fixed_digits() const; UShort fixed_scale() const; }; istream& operator>>(istream& is, Fixed &val); ostream& operator<<(ostream& os, const Fixed &val); Fixed operator + (const Fixed &val1, const Fixed &val2); Fixed operator - (const Fixed &val1, const Fixed &val2); Fixed operator * (const Fixed &val1, const Fixed &val2); Fixed operator / (const Fixed &val1, const Fixed &val2); Fixed operator > (const Fixed &val1, const Fixed &val2); Fixed operator < (const Fixed &val1, const Fixed &val2); Fixed operator >= (const Fixed &val1, const Fixed &val2); Fixed operator <= (const Fixed &val1, const Fixed &val2); Fixed operator == (const Fixed &val1, const Fixed &val2); Fixed operator != (const Fixed &val1, const Fixed &val2); The Fixed class is used directly by the C++ mapping for IDL fixed point constant values and for all intermediate results of arithmetic operations on fixed point values. For fixed point parameters of IDL operations or members of IDL structured datatypes, the implementation may use the Fixed type directly, or alternatively, may use a different type, with an effectively constant digits and scale, that provides the same C++ interface and can be implicitly converted from/to the Fixed class. The name(s) of this alternative class is not defined by this mapping. Since fixed point types used as parameters of IDL operations must be named via an IDL typedef declaration, the mapping must use the typedef to define the type of the operation parameter to make sure that server side operation signatures are portable. The Fixed class has a number of constructors to guarantee that a fixed value can be constructed from any of the IDL standard integer and floating point types. The Fixed(char *) constructor converts a string representation of a fixed point literal into a real fixed point value, with the trailing 'd' or 'D' optional. The Fixed class also provides conversion operators back to the LongLong and LongDouble types. The to_string() function provides an explicit conversion of a fixed point value to a string representation without the trailing 'd' or 'D'. The returned string value must be released by the caller using CORBA::string_free(). The round() and truncate() functions convert a fixed value to a new value with the specified digits and scale. If the new digits and scale require the value to loose precision on the right, the round() function will round away from zero values that are halfway or more to the next absolute value for the new fixed precision. The truncate() function always truncates the value towards zero. So, for example: Fixed f1 = "0.1"; Fixed f2 = "0.05"; Fixed f3 = "-0.005; f1.round(1,0) and f1.truncate(1,0) both return 0., f2.round(2,1) returns 0.1, f2.truncate(2,1) returns 0.0, f3.round(3,2) returns -0.01 and f3.truncate returns 0.00. The fixed_digits() and fixed_scale() functions return the smallest digits and scale value that can hold the complete fixed point value. If the implementation uses alternative classes for operation parameters and structured type members, then fixed_digits() and fixed_scale() return the constant digits and scale values defined by the source IDL fixed point type. Arithmetic operations on the Fixed class must calculate the result exactly, using an effective double precision (62 digit) temporary value. The results are then truncated at run time to fit in a maximum of 31 digits using the method defined in 3.7.2 to determine the new digits and scale. If the result of any arithmetic operation produces more than 31 digits to the left of the decimal point, the DATA_CONVERSION exception will be thrown. If a fixed point value, used as an actual operation parameter or assigned to a member of an IDL structured datatype, exceeds the maximum absolute value implied by the digits and scale, the DATA_CONVERSION exception will be thrown. The stream insertion and extraction operators << and >> convert a fixed point value to/from a stream using the format defined for an IDL fixed point literal. For stream insertion, the trailing 'd' or 'D' is left off, and for stream insertion, the 'd' or 'D' is optional. 20.11.1 Fixed T_var and T_out Types Since fixed point types are always passed by reference as operation parameters and returned by value, there is no need for a _var type for fixed point. For each IDL fixed point typedef a corresponding _out type is defined as a reference to the fixed point type: // IDL typedef fixed<5,2> F; // C++ typedef Implementation_Defined_name F; typedef F &F_out; -------------------------------------------------------------------------------- In section 20.16.2, change the paragraph that reads: For values of type T that are too large to be passed by value efficiently, such as structs, unions, sequences, fixed types, Any, and exceptions, two forms of the insertion function are provided. to: For values of type T that are too large to be passed by value efficiently, such as structs, unions, sequences, Any, and exceptions, two forms of the insertion function are provided. -------------------------------------------------------------------------------- In section 20.16.3, change the paragraph that reads: "For non-primitive types, such as struct, union, sequence, exception, Any, and fixed types, extraction is done by pointer. For example, consider the following IDL struct:" to: For non-primitive types, such as struct, union, sequence, exception, and Any, extraction is done by pointer. For example, consider the following IDL struct: -------------------------------------------------------------------------------- Changed the title of section 20.16.4 to: 20.16.4 Distinguishing boolean, octet, char, wchar, bounded string, bounded wstring and fixed Change the first paragraph to: Since the boolean, octet, char, and wchar OMG IDL types are not required to map to distinct C++ types, another means of distinguishing them from each other is necessary so that they can be used with the type-safe any interface. Similarly, since both bounded and unbounded strings map to char*, both bounded and unbounded wide strings map to WChar*, and all fixed point types map to FixeD, another means of distinguishing them must be provided. This is done by introducing several new helper types nested in the any class interface. Add the following declaration to the Any class right after the corresponding from_wstring/to_wstring references: struct from_fixed { from_fixed(const Fixed &f, UShort d, UShort s) : val(f), digits(d), scale(s) { } const Fixed &val; UShort digits; UShort scale; }; void operator <<=(from_fixed); struct to_fixed { to_fixed(Fixed &f, UShort d, UShort s); Fixed &val; UShort digits; UShort scale; }; void operator >>=(to_fixed) const; Also add these declarations to the Any class in section 20.39.4. Add the following to the end of the example on page 20.54: Fixed f = "123.45"; any <<= Any::from_fixed(f, 5, 2); // ... if (any >>= Any::to_fixed(f, 5, 2)) { // ...any contains a fixed<5,2> } -------------------------------------------------------------------------------- Change the fixed point type row in Table 20-2 to: fixed const Fixed & Fixed & Fixed & Fixed -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: Sender: jon@floorboard.com Date: Tue, 21 Jul 1998 17:05:35 -0700 From: Jonathan Biggar To: cxx_revision@omg.org Subject: Re: Version 2 of proposal to "fix" fixed point in the C++ mapping :-) References: <35B4AEA2.B361FE28@floorboard.com> Jonathan Biggar wrote: > > [Here is version 2 of the proposal. I realized last night that > inserting and extracting fixed point to/from an any required > from_fixed > & to_fixed classes to specify the digits and scale that should be > embedded in the TypeCode. So the parts dealing with any have been > rewritten.] Ok guys, you now had a day or so to look this proposal over. If we are to have any chance to get this into CORBA 2.3, I need feedback quickly! -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: X-Sender: vinoski@mail.boston.iona.ie Date: Tue, 21 Jul 1998 22:53:10 -0400 To: Jonathan Biggar From: Steve Vinoski Subject: Re: Version 2 of proposal to "fix" fixed point in the C++ mapping :-) Cc: cxx_revision@omg.org References: <35B4AEA2.B361FE28@floorboard.com> At 05:05 PM 7/21/98 -0700, Jonathan Biggar wrote: >Jonathan Biggar wrote: >> >> [Here is version 2 of the proposal. I realized last night that >> inserting and extracting fixed point to/from an any required from_fixed >> & to_fixed classes to specify the digits and scale that should be >> embedded in the TypeCode. So the parts dealing with any have been >> rewritten.] > >Ok guys, you now had a day or so to look this proposal over. If we are >to have any chance to get this into CORBA 2.3, I need feedback quickly! Jon, our initial reaction is that it looks pretty good. I will try to look it over in detail tomorrow and will send any comments I might have at that time. --steve Return-Path: Sender: jon@floorboard.com Date: Tue, 21 Jul 1998 21:22:01 -0700 From: Jonathan Biggar To: Steve Vinoski CC: cxx_revision@omg.org Subject: Re: Version 2 of proposal to "fix" fixed point in the C++ mapping :-) References: <35B4AEA2.B361FE28@floorboard.com> <199807220254.WAA10704@boston.iona.ie> Steve Vinoski wrote: > > At 05:05 PM 7/21/98 -0700, Jonathan Biggar wrote: > >Jonathan Biggar wrote: > >> > >> [Here is version 2 of the proposal. I realized last night that > >> inserting and extracting fixed point to/from an any required > from_fixed > >> & to_fixed classes to specify the digits and scale that should be > >> embedded in the TypeCode. So the parts dealing with any have > been > >> rewritten.] > > > >Ok guys, you now had a day or so to look this proposal over. If we > are > >to have any chance to get this into CORBA 2.3, I need feedback > quickly! > > Jon, our initial reaction is that it looks pretty good. I will try > to look > it over in detail tomorrow and will send any comments I might have > at that > time. Just to let you all know, I test compiled the Fixed class from my proposal using the sun 4.2 CC compiler and everything passed with flying colors. One thing I just thought of is that I might have add some text to the istream and ostream operator part to make it clear that the declarations of these operators should be adjusted to handle the ANSIness or lack thereof of the C++ environment. -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Return-Path: X-Sender: vinoski@mail.boston.iona.ie Date: Thu, 23 Jul 1998 19:05:21 -0400 To: Jonathan Biggar From: Steve Vinoski Subject: Re: Version 2 of proposal to "fix" fixed point in the C++ mapping :-) Cc: cxx_revision@omg.org At 08:07 AM 7/21/98 -0700, Jonathan Biggar wrote: >istream& operator>>(istream& is, Fixed &val); Jon, is there a need to define the formats that are acceptable to operator>>? Seems like there is, otherwise programs won't be able to portably read fixed-point input. --steve Return-Path: Sender: jon@floorboard.com Date: Fri, 24 Jul 1998 14:52:37 -0700 From: Jonathan Biggar To: cxx_revision@omg.org Subject: Version 3 of proposal to "fix" fixed point in the C++ mapping :-) [This is version 3 of the fixed point mega-proposal. I have made the following changes: A. I have tightened up the language for the iostream extraction & insertion operators. I have added text that states that the exact version of these should be what is appropriate for the C++ environment. I have also added text that states that formatted fixed input & output is driven by the same format specifiers as for floating-point. B. I have dropped the to_string() function, because using a strstream and inserting a Fixed value gives the programmer more control over the format. C. I added an example of a fixed point constant mapped to C++. D. I have added text clarifying how the conversion from Fixed to other types handles out of bounds cases and truncation when converting to an integral type. E. I have added an example of the mapping to clarify the text requiring the use of the typedef name to make sure that server side signatures are portable. I don't think any of these changes (except perhaps for B) should be considered as substantially modifying the proposal, they are just clarifications and language tightening.] This proposal addresses the following issues: Issue 1056: Fixed types in orbos/98-01-11 Issue 1069: Typos on p 20-34 of orbos/98-01-11 Issue 1070: macros for fixed arithmetic results Issue 1072: fixed_digits and fixed_scale member functions Issue 1073: Missing constructor for Fixed Issue 1092: C++ mapping for fixed is broken (01) Issue 1093: C++ mapping for fixed is broken (02) Issue 1124: C++ Fixed type issue (01) Issue 1125: Fixed type (02) Issue 1126: C++ Fixed Type (03) Issue 1538: Missing text describing fixed point constant mapping Summary description of the problems with fixed: The worst problem with the existing CORBA 2.2 mapping for fixed point types is the attempted use of a template type with the digits and scale as template arguments. This causes two major problems, neither of which is possible to fix without reworking the mapping entirely. The first is that the Fixed is defined as a template in the CORBA namespace. This cannot be implemented in a compiler that does not support either namespaces or member templates. Since there are still quite a few compilers with this deficiency, this is a bad idea for a fundamental type. The second problem is that the arithmetic for fixed point types (particularly the divide operation) defines the digits and scale of the result of binary mathematics operations (+, -, *, /) to depend on the runtime values of the arguments. This cannot be expressed using C++ template declarations, since the digits and scale must be compile time constants. The second problem area with the fixed point mapping is that the mapping totally ignores fixed point constant declarations and how to map them into C++. For an IDL fixed point declaration: const fixed foo = 1.2D; neither the use of the keyword "fixed" without digits and scale parameters, nor the actual fixed point literal, "1.2D" have a mapping into C++. The third major problem area has to do with the IDL grammar itself. The CORBA 2.2 grammar allows fixed point types to be defined anonymously (without a typedef) as IDL operation parameters or return types. But since the C++ mapping specifies that _var and _out types are defined for anonymous fixed point types, this causes two problems: first, the mapping does not define how to handle a negative scale when determining the name for the _var and _out types for an anonymous fixed point type, and second, there is no clear place to define the _var and _out types when an anonymous fixed point type is used as an IDL parameter or return type. Overview of the Proposal: The key to the proposal is to redefine CORBA::Fixed to be a non-template type that can handle any combination of digits and scale at run time. All of the arithmetic operations are defined using CORBA::Fixed. However, this proposal does not require that CORBA::Fixed be used as the type for operation parameters and fields in IDL structured types (struct, union, sequence, array, etc). The reason for this is that a generic fixed point value needs about 18 bytes of storage, minimum--16 for the 31 digits plus sign, 2 for the digits and scale values. So, by allowing the implementation to choose to use another type for fixed point types with an explicit digits and scale, this gives the implementation the flexibility to reduce the storage cost for fixed point types in places where the digits and scale are known. It also allows the implementation to code the bounds check for digits and scale into the conversion between the "generic" CORBA::Fixed type and the actual type used for operation parameters and structured members, rather than having to add code at runtime to check these bounds inside the marshaling engine. In fact, an implementation could still use a template for these unnamed types without the problems described above, since the implementation is free to declare the template however it needs to. The second problem, that the mapping for fixed point constants is not specified, is solved by mapping fixed point constants to normal C++ string literals. The third problem, issues with declaring _out & _var types for fixed point has been mainly resolved by the ORB core RTF, which has already approved a fix that obviate the need for the C++ RTF to fix these problems. The proposal accepted by the core RTF are to forbid the declaration of anonymous fixed types as IDL operation parameters. In addition, the proposal presented here eliminates the _var type for fixed point types, because it is unnecessary. This proposal just treats C++ fixed point types like built-in C++ types. Since a maximal sized fixed point type needs little if any more storage than a long double, which is passed by value, there isn't much need to use dynamic storage (new and delete) for fixed point values. Besides, the C++ mapping specifies that fixed point types are always passed by reference, and never by pointer. The ORB core RTF has also passed a proposal that outlaws the use of a negative scale, since the original CORBA 2.2 specification stated that this was not portable anyway. Proposal: Make the following changes to the CORBA 2.2 C++ mapping (section 20): -------------------------------------------------------------------------------- Add the following paragraphs to the end of section 20.4: Fixed Point Constants Since C++ does not have a native fixed point type, IDL fixed point literals are mapped to C++ strings without the trailing 'd' or 'D' in order to guarantee that there is no loss of precision. For example: // IDL const fixed F = 123.456D; // C++ const Fixed F = "123.456"; -------------------------------------------------------------------------------- Replace the entire text of section 20.11 with: 20.11 Mapping for Fixed The C++ mapping for fixed is defined by the following class: class Fixed { public: // Constructors... Fixed(int val = 0); Fixed(unsigned val); Fixed(Long val); Fixed(ULong val); Fixed(LongLong val); Fixed(ULongLong val); Fixed(Double val); Fixed(LongDouble val); Fixed(const Fixed& val); Fixed(const char *); ~Fixed(); // Conversions... operator LongLong() const; operator LongDouble() const; Fixed round(UShort digits, UShort scale) const; Fixed truncate(UShort digits, UShort scale) const; // Operators... Fixed& operator=(const Fixed& val); Fixed& operator+=(const Fixed& val); Fixed& operator-=(const Fixed& val); Fixed& operator*=(const Fixed& val); Fixed& operator/=(const Fixed& val); Fixed& operator++(); Fixed& operator++(int); Fixed& operator--(); Fixed& operator--(int); Fixed& operator+() const; Fixed& operator-() const; int operator!() const; // Other member functions UShort fixed_digits() const; UShort fixed_scale() const; }; istream& operator>>(istream& is, Fixed &val); ostream& operator<<(ostream& os, const Fixed &val); Fixed operator + (const Fixed &val1, const Fixed &val2); Fixed operator - (const Fixed &val1, const Fixed &val2); Fixed operator * (const Fixed &val1, const Fixed &val2); Fixed operator / (const Fixed &val1, const Fixed &val2); Fixed operator > (const Fixed &val1, const Fixed &val2); Fixed operator < (const Fixed &val1, const Fixed &val2); Fixed operator >= (const Fixed &val1, const Fixed &val2); Fixed operator <= (const Fixed &val1, const Fixed &val2); Fixed operator == (const Fixed &val1, const Fixed &val2); Fixed operator != (const Fixed &val1, const Fixed &val2); The Fixed class is used directly by the C++ mapping for IDL fixed point constant values and for all intermediate results of arithmetic operations on fixed point values. For fixed point parameters of IDL operations or members of IDL structured datatypes, the implementation may use the Fixed type directly, or alternatively, may use a different type, with an effectively constant digits and scale, that provides the same C++ interface and can be implicitly converted from/to the Fixed class. The name(s) of this alternative class is not defined by this mapping. Since fixed point types used as parameters of IDL operations must be named via an IDL typedef declaration, the mapping must use the typedef to define the type of the operation parameter to make sure that server side operation signatures are portable. Here is an example of the mapping: // IDL typedef fixed<5,2> F; interface A { void op(in F arg); }; // C++ typedef Implementation_Defined_Class F; class A { public: ... void op(const F &arg); ... }; The Fixed class has a number of constructors to guarantee that a fixed value can be constructed from any of the IDL standard integer and floating point types. The Fixed(char *) constructor converts a string representation of a fixed point literal into a real fixed point value, with the trailing 'd' or 'D' optional. The Fixed class also provides conversion operators back to the LongLong and LongDouble types. For conversion to integral types, digits to the right of the decimal point are truncated. If the magnitude of the fixed point value does not fit in the target conversion type, then the DATA_CONVERSION system exception is thrown. The round() and truncate() functions convert a fixed value to a new value with the specified digits and scale. If the new digits and scale require the value to loose precision on the right, the round() function will round away from zero values that are halfway or more to the next absolute value for the new fixed precision. The truncate() function always truncates the value towards zero. So, for example: Fixed f1 = "0.1"; Fixed f2 = "0.05"; Fixed f3 = "-0.005; f1.round(1,0) and f1.truncate(1,0) both return 0., f2.round(2,1) returns 0.1, f2.truncate(2,1) returns 0.0, f3.round(3,2) returns -0.01 and f3.truncate returns 0.00. The fixed_digits() and fixed_scale() functions return the smallest digits and scale value that can hold the complete fixed point value. If the implementation uses alternative classes for operation parameters and structured type members, then fixed_digits() and fixed_scale() return the constant digits and scale values defined by the source IDL fixed point type. Arithmetic operations on the Fixed class must calculate the result exactly, using an effective double precision (62 digit) temporary value. The results are then truncated at run time to fit in a maximum of 31 digits using the method defined in 3.7.2 to determine the new digits and scale. If the result of any arithmetic operation produces more than 31 digits to the left of the decimal point, the DATA_CONVERSION exception will be thrown. If a fixed point value, used as an actual operation parameter or assigned to a member of an IDL structured datatype, exceeds the maximum absolute value implied by the digits and scale, the DATA_CONVERSION exception will be thrown. The stream insertion and extraction operators << and >> convert a fixed point value to/from a stream. The exact definition of these operators may vary depending on the level of standardization of the C++ environment. These operators insert and extract fixed point values into the stream using the same format as for C++ floating point types. In particular, the trailing d or D from the IDL fixed point literal representation is not inserted or extracted from the stream. These operators use all format controls appropriate to floating point defined by the stream classes except that they never use the scientific format. 20.11.1 Fixed T_var and T_out Types Since fixed point types are always passed by reference as operation parameters and returned by value, there is no need for a _var type for fixed point. For each IDL fixed point typedef a corresponding _out type is defined as a reference to the fixed point type: // IDL typedef fixed<5,2> F; // C++ typedef Implementation_Defined_name F; typedef F &F_out; -------------------------------------------------------------------------------- In section 20.16.2, change the paragraph that reads: For values of type T that are too large to be passed by value efficiently, such as structs, unions, sequences, fixed types, Any, and exceptions, two forms of the insertion function are provided. to: For values of type T that are too large to be passed by value efficiently, such as structs, unions, sequences, Any, and exceptions, two forms of the insertion function are provided. -------------------------------------------------------------------------------- In section 20.16.3, change the paragraph that reads: "For non-primitive types, such as struct, union, sequence, exception, Any, and fixed types, extraction is done by pointer. For example, consider the following IDL struct:" to: For non-primitive types, such as struct, union, sequence, exception, and Any, extraction is done by pointer. For example, consider the following IDL struct: -------------------------------------------------------------------------------- Changed the title of section 20.16.4 to: 20.16.4 Distinguishing boolean, octet, char, wchar, bounded string, bounded wstring and fixed Change the first paragraph to: Since the boolean, octet, char, and wchar OMG IDL types are not required to map to distinct C++ types, another means of distinguishing them from each other is necessary so that they can be used with the type-safe any interface. Similarly, since both bounded and unbounded strings map to char*, both bounded and unbounded wide strings map to WChar*, and all fixed point types map to FixeD, another means of distinguishing them must be provided. This is done by introducing several new helper types nested in the any class interface. Add the following declaration to the Any class right after the corresponding from_wstring/to_wstring references: struct from_fixed { from_fixed(const Fixed &f, UShort d, UShort s) : val(f), digits(d), scale(s) { } const Fixed &val; UShort digits; UShort scale; }; void operator <<=(from_fixed); struct to_fixed { to_fixed(Fixed &f, UShort d, UShort s); Fixed &val; UShort digits; UShort scale; }; void operator >>=(to_fixed) const; Also add these declarations to the Any class in section 20.39.4. Add the following to the end of the example on page 20.54: Fixed f = "123.45"; any <<= Any::from_fixed(f, 5, 2); // ... if (any >>= Any::to_fixed(f, 5, 2)) { // ...any contains a fixed<5,2> } -------------------------------------------------------------------------------- Change the fixed point type row in Table 20-2 to: fixed const Fixed & Fixed & Fixed & Fixed -- Jon Biggar Floorboard Software jon@floorboard.com jon@biggar.org Date: Sun, 21 Feb 1999 09:00:06 +1000 (EST) From: Michi Henning To: C++ Revision Task Force Subject: Proposal for 1070, 1073, 1092, 1093, 1124, 1125, 1126, 1783 Organization: Triodia Technologies Close these issues as fixed. They were addressed by the Fixed mapping. Cheers, Michi. -- Michi Henning +61 7 3236 1633 Triodia Technologies +61 4 1118 2700 (mobile) PO Box 372 +61 7 3211 0047 (fax) Annerley 4103 michi@triodia.com AUSTRALIA http://www.triodia.com/staff/michi-henning.html