[xint] Design Question

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 I'm adding an "unsigned" option to the XInt library, so that fixed-length integers act exactly like their built-in counterparts. That in itself is not a problem, since unsigned fixed-length integers have a well-known and standard behavior. The problem is: what should the library do if the user asks for an unsigned *non*-fixed-length integer? The options I've come up with so far, in order of my personal preference: A: Make the unsigned option part of the fixed-length option, so it *can't* be specified separately. (The most elegant solution, but perhaps not the most useful.) B: Refuse to compile (or if I can't find a way to do that, instantiate) it, on the grounds that the combination can't logically be supported. C: Throw an exception if any calculation results in a negative number. (Not very useful, but logical because under the built-in types' unsigned rules, a negative number in an unlimited-length library would be infinitely long.) D: Force any negative numbers to a different value, such as zero or maybe their positive counterparts. (I can't think of any use for this, I just put it here for completeness.) Can anyone think of a potential reason for options C or D? Or a reason to prefer option B? Or maybe come up with a different idea entirely? - -- Chad Nelson Oak Circle Software, Inc. * * * -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkwY2EYACgkQp9x9jeZ9/wSZuACgqIjJ85p0wUrwhCR/tcvY8QUL bagAniFZU/UGwKfpK7juhuWYxXwMb2Ar =qvcJ -----END PGP SIGNATURE-----

----- Original Message ----- From: "Chad Nelson" <chad.thecomfychair@gmail.com> To: <boost@lists.boost.org> Sent: Wednesday, June 16, 2010 3:57 PM Subject: [boost] [xint] Design Question
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
I'm adding an "unsigned" option to the XInt library, so that fixed-length integers act exactly like their built-in counterparts. That in itself is not a problem, since unsigned fixed-length integers have a well-known and standard behavior.
The problem is: what should the library do if the user asks for an unsigned *non*-fixed-length integer?
Can anyone think of a potential reason for options C or D? Or a reason to prefer option B? Or maybe come up with a different idea entirely?
What about making the difference between two unsigned integers a signed integer? Regards, Vicente

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 06/16/2010 02:31 PM, vicente.botet wrote:
The problem is: what should the library do if the user asks for an unsigned *non*-fixed-length integer? [...]
What about making the difference between two unsigned integers a signed integer?
That sounds like a useful behavior, but if the developer using the library says it should be an unsigned number, I don't think the library should override that. - -- Chad Nelson Oak Circle Software, Inc. * * * -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkwZQlUACgkQp9x9jeZ9/wScJACfVW40zf+rNY7FWqrLp83FFPOo v90Ani0QcORKSt0n5HsGK4j3bripuPgD =4l13 -----END PGP SIGNATURE-----

On 6/16/2010 2:30 PM, Chad Nelson wrote:
On 06/16/2010 02:31 PM, vicente.botet wrote:
The problem is: what should the library do if the user asks for an unsigned *non*-fixed-length integer? [...]
What about making the difference between two unsigned integers a signed integer?
That sounds like a useful behavior, but if the developer using the library says it should be an unsigned number, I don't think the library should override that.
I think Vicente probably had operator- in mind. Then you'd need signed <-> unsigned conversions, but I'd think that would be expected. For something like operator-=, it probably makes sense to throw an exception, or if the policy parameters disable exceptions, the result should be a singular value. Of course, this could be *another* policy parameter, as I can see clamp-to-zero also making sense. I don't think you should disable use of unsigned, arbitrary-length integers. - Jeff

----- Original Message ----- From: "Jeffrey Lee Hellrung, Jr." <jhellrung@ucla.edu> To: <boost@lists.boost.org> Sent: Wednesday, June 16, 2010 11:31 PM Subject: Re: [boost] [xint] Design Question
On 6/16/2010 2:30 PM, Chad Nelson wrote:
On 06/16/2010 02:31 PM, vicente.botet wrote:
The problem is: what should the library do if the user asks for an unsigned *non*-fixed-length integer? [...]
What about making the difference between two unsigned integers a signed integer?
That sounds like a useful behavior, but if the developer using the library says it should be an unsigned number, I don't think the library should override that.
I think Vicente probably had operator- in mind. Then you'd need signed <-> unsigned conversions, but I'd think that would be expected.
Yes, I expected signed <-> unsigned conversions, and an exception if the signed is < 0. The user can always test if the signed is <0 and do whatever s/he thinks is better for its application if s/he wants a unsigned value.
I don't think you should disable use of unsigned, arbitrary-length integers. +1
Best, Vicente

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 06/16/2010 05:31 PM, Jeffrey Lee Hellrung, Jr. wrote:
What about making the difference between two unsigned integers a signed integer?
That sounds like a useful behavior, but if the developer using the library says it should be an unsigned number, I don't think the library should override that.
I think Vicente probably had operator- in mind. Then you'd need signed <-> unsigned conversions, but I'd think that would be expected.
I have (explicit) conversion constructors for translating between different types of integer. I assume that's what you meant?
For something like operator-=, it probably makes sense to throw an exception, or if the policy parameters disable exceptions, the result should be a singular value. Of course, this could be *another* policy parameter, as I can see clamp-to-zero also making sense.
:-? I think I'm going to need some help with Boost.Parameter to implement that. I had quite a time figuring out how to get just *one* value per template parameter, in a way that would compile on MSVC too. I'm not sure how to get more than one.
I don't think you should disable use of unsigned, arbitrary-length integers.
That's why I asked. :-) - -- Chad Nelson Oak Circle Software, Inc. * * * -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkwZi2EACgkQp9x9jeZ9/wQkDACaA20e8TRIfMCV91vpXYi348Ss GiQAoMg6wvIaqSCt375EnMv1embBeThg =Njy0 -----END PGP SIGNATURE-----

Chad Nelson wrote:
On 06/16/2010 02:31 PM, vicente.botet wrote:
The problem is: what should the library do if the user asks for an unsigned *non*-fixed-length integer? [...]
What about making the difference between two unsigned integers a signed integer?
That sounds like a useful behavior, but if the developer using the library says it should be an unsigned number, I don't think the library should override that.
According to an old C book I have (C: A Reference Manual, 2nd ed, Harbison and Steele), "the result of subtracting one unsigned integer from another is always unsigned and therefore cannot be negative." That may not be definitive, and the C++ standard doesn't dictate the type of the result other than, perhaps, by incorporating the C standard to which I have no access, but it certainly sets expectations that your library ought not violate. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 06/17/2010 07:10 AM, Stewart, Robert wrote:
What about making the difference between two unsigned integers a signed integer?
That sounds like a useful behavior, but if the developer using the library says it should be an unsigned number, I don't think the library should override that.
According to an old C book I have (C: A Reference Manual, 2nd ed, Harbison and Steele), "the result of subtracting one unsigned integer from another is always unsigned and therefore cannot be negative."
Yes, that's the way I've always understood it. I've often taken advantage of that too -- typecasting -1 to an unsigned type gives a value with all bits on, and doesn't require you to know how many bits that type has beforehand. (Yes, there are other ways to do it, like with operator~.)
That may not be definitive, and the C++ standard doesn't dictate the type of the result other than, perhaps, by incorporating the C standard to which I have no access, but it certainly sets expectations that your library ought not violate.
Pretty much what I was thinking. - -- Chad Nelson Oak Circle Software, Inc. * * * -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkwaR3IACgkQp9x9jeZ9/wRuJwCgtAfWrgJyNbq9BH3Sn3Cl/Vpu bO0AoPy4wtImsWECayMJgqmcfcdtWVnm =WIg2 -----END PGP SIGNATURE-----

----- Original Message ----- From: "Stewart, Robert" <Robert.Stewart@sig.com> To: <boost@lists.boost.org> Sent: Thursday, June 17, 2010 1:10 PM Subject: Re: [boost] [xint] Design Question
Chad Nelson wrote:
On 06/16/2010 02:31 PM, vicente.botet wrote:
The problem is: what should the library do if the user asks for an unsigned *non*-fixed-length integer? [...]
What about making the difference between two unsigned integers a signed integer?
That sounds like a useful behavior, but if the developer using the library says it should be an unsigned number, I don't think the library should override that.
According to an old C book I have (C: A Reference Manual, 2nd ed, Harbison and Steele), "the result of subtracting one unsigned integer from another is always unsigned and therefore cannot be negative." That may not be definitive, and the C++ standard doesn't dictate the type of the result other than, perhaps, by incorporating the C standard to which I have no access, but it certainly sets expectations that your library ought not violate.
This is a good option for fixed size unsigned integers, but not necesary for unlimited size unsigned integers. Vicente

On 16 June 2010 06:57, Chad Nelson <chad.thecomfychair@gmail.com> wrote:
C: Throw an exception if any calculation results in a negative number. (Not very useful, but logical because under the built-in types' unsigned rules, a negative number in an unlimited-length library would be infinitely long.)
That results in look-before-you leap, which is probably bad for speed here, since the subtraction is similar in cost to the comparison. Though it does feel like the best option for operator--(), since there the look is cheap.
D: Force any negative numbers to a different value, such as zero or maybe their positive counterparts. (I can't think of any use for this, I just put it here for completeness.)
Force to zero is "saturation", which is a legitimate desire in certain situations, so it might not be as useless as you think. Making subtraction be absolute difference in an interesting option, since it at least keeps the a-b = 0 <=> a = b equivalence intact.
Can anyone think of a potential reason for options C or D? Or a reason to prefer option B? Or maybe come up with a different idea entirely?
How about this combo of B, C, and D: - if !i, --i and i-- both throw exceptions. - a - b doesn't compile for non-fixed length - provide a separate absdiff(a, b) function ~ Scott

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 06/16/2010 09:32 PM, Scott McMurray wrote:
[...] Can anyone think of a potential reason for options C or D? Or a reason to prefer option B? Or maybe come up with a different idea entirely?
How about this combo of B, C, and D: - if !i, --i and i-- both throw exceptions. - a - b doesn't compile for non-fixed length - provide a separate absdiff(a, b) function
Do you know of any way, short of making two nearly-identical copies of the integer_t class template, to provide different functions? I tried using multiple templated base classes, but the compiler seemed unable to find the inherited functions at all that way, for reasons I don't understand. (That's why the current setup isn't exactly how policy-based design is described, and why all different integer_t types have exactly the same functions, even when they don't make sense for that particular type of integer.) If you want examples of the problem, I'll have to work some up again. I was more interested in getting it to work, so I didn't save any. - -- Chad Nelson Oak Circle Software, Inc. * * * -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkwZj/kACgkQp9x9jeZ9/wTuIQCg+VEGwb+Yautuw/WdJvzY7xnY s/4AoPaVMZaMpShUazk7O8+U9pADrA+q =IP2i -----END PGP SIGNATURE-----

On 16 June 2010 20:01, Chad Nelson <chad.thecomfychair@gmail.com> wrote:
Do you know of any way, short of making two nearly-identical copies of the integer_t class template, to provide different functions? I tried using multiple templated base classes, but the compiler seemed unable to find the inherited functions at all that way, for reasons I don't understand.
SFINAE, through enable_if and disable_if? Without more details, it's hard to know what you're asking for.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 06/17/2010 12:00 AM, Scott McMurray wrote:
Do you know of any way, short of making two nearly-identical copies of the integer_t class template, to provide different functions? I tried using multiple templated base classes, but the compiler seemed unable to find the inherited functions at all that way, for reasons I don't understand.
SFINAE, through enable_if and disable_if?
Without more details, it's hard to know what you're asking for.
When I went looking for a description of policy-based design, it appeared to use multiple base classes, each one providing the functions and data specific to its own policy. But when I tried adapting my existing design to that, by putting the functions specific to each policy into their own classes, the compiler couldn't seem to find the functions that should have been inherited. Let me see if I can come up with some code to demonstrate the problem... Hm. I think I've figured it out now: for some reason, at least under GCC, this code would fail: - --------------------------8<------------------------------ #include <iostream> using std::cout; using std::endl; template <bool Value> class Policy1 { public: void test_policy1() { cout << "Policy1: " << Value << endl; } }; template <int Value> class Policy2 { public: void test_policy2() { cout << "Policy2: " << Value << endl; } }; template <bool P1, int P2> class CombinePolicies: public Policy1<P1>, public Policy2<P2> { public: void test() { test_policy1(); test_policy2(); } }; int main() { CombinePolicies<true, 3> t; t.test(); } - --------------------------8<------------------------------ The compiler reports "there are no arguments to 'test_policy1' that depend on a template parameter, so a declaration of 'test_policy1' must be available". Same error for test_policy2. I could call either one from *outside* the CombinePolicies class, but from inside, they would always give that error. As I said above, I think I figured out the solution. While writing that code just now, it occurred to me to try this... Policy1<P1>::test_policy1(); Policy2<P2>::test_policy2(); ...and it worked. But I don't understand why it failed in the first place. Those two function names are unique in the class, and they're obviously inherited because I can call them from outside the class. Why aren't they visible without the base class name from *within* the combined class? - -- Chad Nelson Oak Circle Software, Inc. * * * -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkwZrWYACgkQp9x9jeZ9/wRonwCfXOAQ9EXUeP4GII1gF5b8k5ry IG4AmQFyuDq8HtmWls5Ckss3aJvN8ZkJ =Vfxv -----END PGP SIGNATURE-----

On 6/16/2010 10:06 PM, Chad Nelson wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 06/17/2010 12:00 AM, Scott McMurray wrote:
Do you know of any way, short of making two nearly-identical copies of the integer_t class template, to provide different functions? I tried using multiple templated base classes, but the compiler seemed unable to find the inherited functions at all that way, for reasons I don't understand.
SFINAE, through enable_if and disable_if?
Without more details, it's hard to know what you're asking for.
When I went looking for a description of policy-based design, it appeared to use multiple base classes, each one providing the functions and data specific to its own policy. But when I tried adapting my existing design to that, by putting the functions specific to each policy into their own classes, the compiler couldn't seem to find the functions that should have been inherited. Let me see if I can come up with some code to demonstrate the problem...
Hm. I think I've figured it out now: for some reason, at least under GCC, this code would fail:
- --------------------------8<------------------------------
#include<iostream>
using std::cout; using std::endl;
template<bool Value> class Policy1 { public: void test_policy1() { cout<< "Policy1: "<< Value<< endl; } };
template<int Value> class Policy2 { public: void test_policy2() { cout<< "Policy2: "<< Value<< endl; } };
template<bool P1, int P2> class CombinePolicies: public Policy1<P1>, public Policy2<P2> { public: void test() { test_policy1(); test_policy2(); } };
int main() { CombinePolicies<true, 3> t; t.test(); }
- --------------------------8<------------------------------
The compiler reports "there are no arguments to 'test_policy1' that depend on a template parameter, so a declaration of 'test_policy1' must be available". Same error for test_policy2. I could call either one from *outside* the CombinePolicies class, but from inside, they would always give that error.
As I said above, I think I figured out the solution. While writing that code just now, it occurred to me to try this...
Policy1<P1>::test_policy1(); Policy2<P2>::test_policy2();
...and it worked. But I don't understand why it failed in the first place. Those two function names are unique in the class, and they're obviously inherited because I can call them from outside the class. Why aren't they visible without the base class name from *within* the combined class?
In short: Your base classes are dependent types, so using anything from them (functions, types, templates, etc.) will have to be explicitly qualified (as you've discovered) or brought into the derived class' scope with a using declaration. In (not-so) long: For example, http://womble.decadentplace.org.uk/c++/template-faq.html#base-lookup - Jeff

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 06/17/2010 01:16 AM, Jeffrey Lee Hellrung, Jr. wrote:
[...] But I don't understand why it failed in the first place. [...] Why aren't they visible without the base class name from *within* the combined class?
In short: Your base classes are dependent types, so using anything from them (functions, types, templates, etc.) will have to be explicitly qualified (as you've discovered) or brought into the derived class' scope with a using declaration.
In (not-so) long: For example,
http://womble.decadentplace.org.uk/c++/template-faq.html#base-lookup
Ugly, but I can see the reasoning behind it now. Thanks, to you and Scott McMurray, and the person who sent a private e-mail referring me to the same page (who I assume wishes to remain anonymous). I can't tell from that page, but I assume that using the "standard" method (i.e. specifying the full base class name before the function name) will work on what that page calls "intermediate" and "CFront" compilers as well? In other words, does anyone here know of any compatibility problems caused by that, or by a "using" directive in the class to do the same thing? - -- Chad Nelson Oak Circle Software, Inc. * * * -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkwZtGwACgkQp9x9jeZ9/wQ6VwCg6W4fefn7+ju4PNKOPYRPlRoQ ShwAn1/Xpdgr1ZGFguY8Fwdlzq1nadAB =DzL5 -----END PGP SIGNATURE-----

Chad Nelson wrote:
On 06/17/2010 01:16 AM, Jeffrey Lee Hellrung, Jr. wrote:
[...] But I don't understand why it failed in the first place. [...] Why aren't they visible without the base class name from *within* the combined class?
In short: Your base classes are dependent types, so using anything from them (functions, types, templates, etc.) will have to be explicitly qualified (as you've discovered) or brought into the derived class' scope with a using declaration.
http://womble.decadentplace.org.uk/c++/template-faq.html#base-lookup
I can't tell from that page, but I assume that using the "standard" method (i.e. specifying the full base class name before the function name) will work on what that page calls "intermediate" and "CFront" compilers as well? In other words, does anyone here know of any compatibility problems caused by that, or by a "using" directive in the class to do the same thing?
I don't think either would cause a problem, but it is typical to reference policy class member functions using scope resolution. That even permits the policies to use the same function names, though it is generally good to avoid that. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On 16 June 2010 22:06, Chad Nelson <chad.thecomfychair@gmail.com> wrote:
...and it worked. But I don't understand why it failed in the first place. Those two function names are unique in the class, and they're obviously inherited because I can call them from outside the class. Why aren't they visible without the base class name from *within* the combined class?
Because when the compiler is handling the template (rather than an instantiation of the template), the base classes can be arbitrarily specialized, so it has no idea what's in them. At the same time, it wants to be able to give as many error messages as it can, so you don't have to wait until you instantiate the member function to find out that you typed get_bats() instead of get_bits. So its compromise is that if you use an identifier that's not clearly a member, it will give an error message. As you've found out, you can make something clearly a member by saying type::foo or this->bar. And before all the language lawyers wince at my hand-waving, see Jeffrey's reply for a more precise answer.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 06/16/2010 09:32 PM, Scott McMurray wrote:
Can anyone think of a potential reason for options C or D? Or a reason to prefer option B? Or maybe come up with a different idea entirely?
How about this combo of B, C, and D: - if !i, --i and i-- both throw exceptions. - a - b doesn't compile for non-fixed length - provide a separate absdiff(a, b) function
Working on this option now. After looking at it, removing the binary operator- seems rather harsh... if you know that a number is larger than what you're subtracting from it, it would just be irritating. But I'll definitely add the absdiff function (maybe named "difference"?), then the developer using the library can decide which to use for himself. - -- Chad Nelson Oak Circle Software, Inc. * * * -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkwbg94ACgkQp9x9jeZ9/wQ0PgCfZZzb3qYR0djsZPN37GZ1A8XW heIAniFIZd7Zx+rekceANEMaTtX4/oN5 =EOyS -----END PGP SIGNATURE-----

On Fri, Jun 18, 2010 at 8:34 AM, Chad Nelson <chad.thecomfychair@gmail.com> wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 06/16/2010 09:32 PM, Scott McMurray wrote:
Can anyone think of a potential reason for options C or D? Or a reason to prefer option B? Or maybe come up with a different idea entirely?
How about this combo of B, C, and D: - if !i, --i and i-- both throw exceptions. - a - b doesn't compile for non-fixed length - provide a separate absdiff(a, b) function
Working on this option now. After looking at it, removing the binary operator- seems rather harsh... if you know that a number is larger than what you're subtracting from it, it would just be irritating. But I'll definitely add the absdiff function (maybe named "difference"?), then the developer using the library can decide which to use for himself.
Why not just go the simple route and define it as "undefined behaviour", then just pretend they will never get a negative number and let your math functions choke on it as they wish, making invalid values, dividing by zero, whatever, it is "undefined behaviour" after all.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 10-07-09 02:27 AM, OvermindDL1 wrote:
Working on this option now. After looking at it, removing the binary operator- seems rather harsh... if you know that a number is larger than what you're subtracting from it, it would just be irritating. But I'll definitely add the absdiff function (maybe named "difference"?), then the developer using the library can decide which to use for himself.
Why not just go the simple route and define it as "undefined behaviour", then just pretend they will never get a negative number and let your math functions choke on it as they wish, making invalid values, dividing by zero, whatever, it is "undefined behaviour" after all.
For something as simple and common as subtraction, that seems rather harsh too. But in any case, the problem is solved; when you declare an integer to be unsigned, you also have to tell it how to handle operations that result in negative numbers. - -- Chad Nelson Oak Circle Software, Inc. * * * -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkw3MCoACgkQp9x9jeZ9/wQ8JACgijcm+lyLXn5UJf3z/L/Bd3lm xyUAoIl6EqgCW3FsfR8ldjhTVo/EgEfj =Wxp+ -----END PGP SIGNATURE-----

On 8 July 2010 23:27, OvermindDL1 <overminddl1@gmail.com> wrote:
Why not just go the simple route and define it as "undefined behaviour", then just pretend they will never get a negative number and let your math functions choke on it as they wish, making invalid values, dividing by zero, whatever, it is "undefined behaviour" after all.
I think that's somewhat too severe, since one of the reasons for using an unlimited-precision integer it to avoid UB and IDB.

Chad Nelson wrote:
The options I've come up with so far, in order of my personal preference:
A: Make the unsigned option part of the fixed-length option, so it *can't* be specified separately. (The most elegant solution, but perhaps not the most useful.)
B: Refuse to compile (or if I can't find a way to do that, instantiate) it, on the grounds that the combination can't logically be supported.
There are legitimate uses, I should think, so these options don't seem right.
C: Throw an exception if any calculation results in a negative number. (Not very useful, but logical because under the built-in types' unsigned rules, a negative number in an unlimited-length library would be infinitely long.)
As I replied to another post on this question, it appears the correct behavior is for negative results -- for subtraction, anyway -- to be impossible. That, of course, requires modulus behavior and your purpose, here, is to provide unlimited size, so there's no underflow possible. I'm not certain that an exception is the most reasonable recourse, however. In code that never expects to produce negative results, even checking for a negative value is unwanted overhead. Wouldn't it be better to simply permit such an operation to result in memory exhaustion? That would get the attention of the program in short order without the tests and exception. You can also include checked modes -- a variation of a policy, perhaps -- that on negative values asserts, throws, etc. That would leave the choice to the client.
D: Force any negative numbers to a different value, such as zero or maybe their positive counterparts. (I can't think of any use for this, I just put it here for completeness.)
I think Scott suggested there was value in this scheme, so making the behavior a policy makes ever more sense. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 06/17/2010 07:21 AM, Stewart, Robert wrote:
The options I've come up with so far, in order of my personal preference:
A: Make the unsigned option part of the fixed-length option, so it *can't* be specified separately. (The most elegant solution, but perhaps not the most useful.)
B: Refuse to compile (or if I can't find a way to do that, instantiate) it, on the grounds that the combination can't logically be supported.
There are legitimate uses, I should think, so these options don't seem right.
I couldn't think of any legitimate reason for an unsigned unlimited-length integer, given the inability to act the way the built-in unsigned types do. That's why I asked.
C: Throw an exception if any calculation results in a negative number. (Not very useful, but logical because under the built-in types' unsigned rules, a negative number in an unlimited-length library would be infinitely long.)
As I replied to another post on this question, it appears the correct behavior is for negative results -- for subtraction, anyway -- to be impossible. That, of course, requires modulus behavior and your purpose, here, is to provide unlimited size, so there's no underflow possible.
Exactly.
I'm not certain that an exception is the most reasonable recourse, however. In code that never expects to produce negative results, even checking for a negative value is unwanted overhead. Wouldn't it be better to simply permit such an operation to result in memory exhaustion? That would get the attention of the program in short order without the tests and exception.
The same way that a "bunker buster" bomb gets the attention of an ant it's dropped on. ;-) But no, that would take extra code, as well as the aforementioned "unwanted overhead" check. The library just isn't set up to fail that way.
You can also include checked modes -- a variation of a policy, perhaps -- that on negative values asserts, throws, etc. That would leave the choice to the client.
That seems to be the consensus. So far it looks like there should be four options: * Modulus (only available on fixed-length types); * Throw exception; * Force to zero (for "saturation"); * Force to absolute value of number (possibly via a different function). I suspect it'll be at least a few days before I can upload a version with that feature, because I want to make some other improvements that I've recently discovered are possible first. - -- Chad Nelson Oak Circle Software, Inc. * * * -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkwaTTAACgkQp9x9jeZ9/wRxZACfQgC5v88Uym8QGWzvoeVb5W6A LIoAoMbvVW5mvhFuhKEGYZ6gX7/auli1 =nx0E -----END PGP SIGNATURE-----

On 06/17/2010 06:28 PM, Chad Nelson wrote:
That seems to be the consensus. So far it looks like there should be four options:
* Modulus (only available on fixed-length types);
* Throw exception;
* Force to zero (for "saturation");
* Force to absolute value of number (possibly via a different function).
I suspect it'll be at least a few days before I can upload a version with that feature, because I want to make some other improvements that I've recently discovered are possible first.
I recall of a discussion here about NaN in xint. It could be used at least for NoThrow variants (especially if the 'Throw exception' option is chosen). By the way, are there +inf/-inf values for xint ? -- Maxime

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 06/17/2010 01:23 PM, Maxime van Noppen wrote:
That seems to be the consensus. So far it looks like there should be four options: [...]
I recall of a discussion here about NaN in xint. It could be used at least for NoThrow variants (especially if the 'Throw exception' option is chosen).
Yes, and it would be.
By the way, are there +inf/-inf values for xint ?
Not at present. They're not countable numbers. - -- Chad Nelson Oak Circle Software, Inc. * * * -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkwaiAkACgkQp9x9jeZ9/wR+vQCfdDxECfRG8JrcopITnzB1Ci1f S3UAniu4ThA/gFV00a2XnKd50lOWOdm7 =gYwq -----END PGP SIGNATURE-----
participants (7)
-
Chad Nelson
-
Jeffrey Lee Hellrung, Jr.
-
Maxime van Noppen
-
OvermindDL1
-
Scott McMurray
-
Stewart, Robert
-
vicente.botet