|
|
Home » Developing U++ » U++ Developers corner » Value with type float
|
Re: Value with type float [message #58367 is a reply to message #58295] |
Tue, 10 May 2022 13:21 |
Tom1
Messages: 1253 Registered: March 2007
|
Senior Contributor |
|
|
Hi Mirek,
Sorry to return to this subject, but could you consider adding Null support for float?
I had something like this in mind... (in Core/Defs.h):
const int INT_NULL = INT_MIN;
const int64 INT64_NULL = INT64_MIN;
constexpr double DOUBLE_NULL = -std::numeric_limits<double>::infinity();
constexpr float FLOAT_NULL = -std::numeric_limits<float>::infinity();
class Nuller {
public:
operator int() const { return INT_NULL; }
operator int64() const { return INT64_NULL; }
operator double() const { return DOUBLE_NULL; }
operator float() const { return FLOAT_NULL; }
operator bool() const { return false; }
Nuller() {}
};
extern const Nuller Null;
template <class T> void SetNull(T& x) { x = Null; }
template <class T> bool IsNull(const T& x) { return x.IsNullInstance(); }
template<> inline bool IsNull(const int& i) { return i == INT_NULL; }
template<> inline bool IsNull(const int64& i) { return i == INT64_NULL; }
template<> inline bool IsNull(const double& r) { return !(std::abs(r) < std::numeric_limits<double>::infinity()); }
template<> inline bool IsNull(const float& r) { return !(std::abs(r) < std::numeric_limits<float>::infinity()); }
template<> inline bool IsNull(const bool& r ) { return false; }
Although, I'm not entirely sure, if this is completely correct way to do it.
Best regards,
Tom
PS. EDIT: I think the above should work mostly. Only the "Cout() << FLOAT_NULL;" prints -inf instead of empty field, which is the default for "Cout() << DOUBLE_NULL;":
CONSOLE_APP_MAIN{
double d=Null;
float f=Null;
double a=f;
float b=d;
Cout() << "d = " << d << "\n";
Cout() << "f = " << f << "\n";
Cout() << "a = " << a << "\n";
Cout() << "b = " << b << "\n";
Cout() << "a == f : " << (bool)(a==f) << "\n";
Cout() << "b == d : " << (bool)(b==d) << "\n";
Cout() << "IsNull(d) = " << IsNull(d) << "\n";
Cout() << "IsNull(f) = " << IsNull(f) << "\n";
Cout() << "IsNull(a) = " << IsNull(a) << "\n";
Cout() << "IsNull(b) = " << IsNull(b) << "\n";
}
[Updated on: Tue, 10 May 2022 13:31] Report message to a moderator
|
|
|
Re: Value with type float [message #58368 is a reply to message #58367] |
Tue, 10 May 2022 15:44 |
|
mirek
Messages: 14113 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Tue, 10 May 2022 13:21Hi Mirek,
Sorry to return to this subject, but could you consider adding Null support for float?
I had something like this in mind... (in Core/Defs.h):
const int INT_NULL = INT_MIN;
const int64 INT64_NULL = INT64_MIN;
constexpr double DOUBLE_NULL = -std::numeric_limits<double>::infinity();
constexpr float FLOAT_NULL = -std::numeric_limits<float>::infinity();
class Nuller {
public:
operator int() const { return INT_NULL; }
operator int64() const { return INT64_NULL; }
operator double() const { return DOUBLE_NULL; }
operator float() const { return FLOAT_NULL; }
operator bool() const { return false; }
Nuller() {}
};
extern const Nuller Null;
template <class T> void SetNull(T& x) { x = Null; }
template <class T> bool IsNull(const T& x) { return x.IsNullInstance(); }
template<> inline bool IsNull(const int& i) { return i == INT_NULL; }
template<> inline bool IsNull(const int64& i) { return i == INT64_NULL; }
template<> inline bool IsNull(const double& r) { return !(std::abs(r) < std::numeric_limits<double>::infinity()); }
template<> inline bool IsNull(const float& r) { return !(std::abs(r) < std::numeric_limits<float>::infinity()); }
template<> inline bool IsNull(const bool& r ) { return false; }
Although, I'm not entirely sure, if this is completely correct way to do it.
Best regards,
Tom
PS. EDIT: I think the above should work mostly. Only the "Cout() << FLOAT_NULL;" prints -inf instead of empty field, which is the default for "Cout() << DOUBLE_NULL;":
CONSOLE_APP_MAIN{
double d=Null;
float f=Null;
double a=f;
float b=d;
Cout() << "d = " << d << "\n";
Cout() << "f = " << f << "\n";
Cout() << "a = " << a << "\n";
Cout() << "b = " << b << "\n";
Cout() << "a == f : " << (bool)(a==f) << "\n";
Cout() << "b == d : " << (bool)(b==d) << "\n";
Cout() << "IsNull(d) = " << IsNull(d) << "\n";
Cout() << "IsNull(f) = " << IsNull(f) << "\n";
Cout() << "IsNull(a) = " << IsNull(a) << "\n";
Cout() << "IsNull(b) = " << IsNull(b) << "\n";
}
IDK. Does it solve any real problem?
Up until this year, I have considered double-float relation to be similar to int-int16. You use float to reduce memory consumption or for special things (GPU), but you really do not need to support it in Value or widgets. Served me well for many many years. What has changed?
Mirek
|
|
|
Re: Value with type float [message #58369 is a reply to message #58368] |
Tue, 10 May 2022 20:08 |
Tom1
Messages: 1253 Registered: March 2007
|
Senior Contributor |
|
|
Hi,
What has changed is that I have really started to enjoy the new EditFloatSpin!
As a result, initializing and reading my float variables to/from EditFloatSpin (as used in e.g. filter parameters) is clean and easy. However, I found that initializing my EditFloatSpin to empty field (e.g. when such filtering is not currently used) requires my float variable to be at Null:
EditFloatSpin hpfedit;
...
float hpf=(float)(double)Null;
...
hpfedit <<= hpf;
Alternatively, some value of hpf (e.g.< 0) could be interpreted as empty filtering and I could do hpfedit.Clear(); if such is the case.
However, I prefer nice, short and clean code, so I would like to write just:
I.e. without any type cast. So, in effect, this is just to make the code cleaner.
Best regards,
Tom
[Updated on: Tue, 10 May 2022 20:28] Report message to a moderator
|
|
|
Re: Value with type float [message #58370 is a reply to message #58369] |
Tue, 10 May 2022 21:26 |
|
mirek
Messages: 14113 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Tue, 10 May 2022 20:08Hi,
What has changed is that I have really started to enjoy the new EditFloatSpin!
As a result, initializing and reading my float variables to/from EditFloatSpin (as used in e.g. filter parameters) is clean and easy. However, I found that initializing my EditFloatSpin to empty field (e.g. when such filtering is not currently used) requires my float variable to be at Null:
EditFloatSpin hpfedit;
...
float hpf=(float)(double)Null;
...
hpfedit <<= hpf;
Alternatively, some value of hpf (e.g.< 0) could be interpreted as empty filtering and I could do hpfedit.Clear(); if such is the case.
However, I prefer nice, short and clean code, so I would like to write just:
I.e. without any type cast. So, in effect, this is just to make the code cleaner.
Best regards,
Tom
Why dont you just use
double hpf;
?
|
|
|
Re: Value with type float [message #58373 is a reply to message #58370] |
Wed, 11 May 2022 08:20 |
Tom1
Messages: 1253 Registered: March 2007
|
Senior Contributor |
|
|
Quote:
Why dont you just use
double hpf;
?
Well, all my signal processing code runs on 32-bit floats, and therefore, the various coefficients/parameters are also floats. It is straight forward to keep it up in the user interface too. If I used doubles in the GUI, I would end up converting forth and back all those parameters. Never wish to go back there, now that I have EditFloat and EditFloatSpin!
Anyway, if you feel seriously reluctant to add Null support for float, I can live with it: I figured out a way to do it outside of Core almost cleanly:
constexpr float Nullf = -std::numeric_limits<float>::infinity();
inline bool IsNull(const float& r) { return !(std::abs(r) < std::numeric_limits<float>::infinity()); }
inline void SetNull(float& x) { x = Nullf; }
Still, it would be nicer inside Core... After all, it would introduce only three lines of new code in Core/Defs.h.
Best regards,
Tom
|
|
|
Re: Value with type float [message #58501 is a reply to message #58373] |
Fri, 03 June 2022 10:52 |
|
mirek
Messages: 14113 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Wed, 11 May 2022 08:20Quote:
Why dont you just use
double hpf;
?
Well, all my signal processing code runs on 32-bit floats, and therefore, the various coefficients/parameters are also floats. It is straight forward to keep it up in the user interface too. If I used doubles in the GUI, I would end up converting forth and back all those parameters. Never wish to go back there, now that I have EditFloat and EditFloatSpin!
Anyway, if you feel seriously reluctant to add Null support for float, I can live with it: I figured out a way to do it outside of Core almost cleanly:
constexpr float Nullf = -std::numeric_limits<float>::infinity();
inline bool IsNull(const float& r) { return !(std::abs(r) < std::numeric_limits<float>::infinity()); }
inline void SetNull(float& x) { x = Nullf; }
Still, it would be nicer inside Core... After all, it would introduce only three lines of new code in Core/Defs.h.
Best regards,
Tom
Got a new idea for a bit more universal solution:
The most important difference between Value(double) and Value(float) is the precision used when formatting it. What about to add a general precision hint to Value(double)? That would make possible to e.g. specify arbitrary precision for Json output etc...
|
|
|
Re: Value with type float [message #58503 is a reply to message #58501] |
Fri, 03 June 2022 12:03 |
Tom1
Messages: 1253 Registered: March 2007
|
Senior Contributor |
|
|
Hi Mirek,
Sounds interesting, but I cannot really figure out all consequences this change may have. If I may express my needs from the user's viewpoint, I hope:
- I can use Value with float as easily as with double without explicit type casts anywhere
- Assigning a float to Value reads back from Value exactly the same as it went in
- If EditFloat* is again replaced by EditDouble*, the behavior is exactly the same as it is now with EditFloat*
- float supports Null
Maybe the precision hint you are suggesting could be automatically initialized in Value(double) / Value(float) constructors and assignment operators =(double) / =(float) to suit the assigned data type?
Best regards,
Tom
|
|
|
|
Re: Value with type float [message #58808 is a reply to message #58807] |
Tue, 06 September 2022 22:42 |
Oblivion
Messages: 1136 Registered: August 2007
|
Senior Contributor |
|
|
Hello jimlef,
Do you mean this?
RLOG(Format(
"Pi(2): %.02f\n"
"PI(4): %.04f\n"
"PI(8): %.08f\n",
roundr(M_PI, 2),
roundr(M_PI, 4),
roundr(M_PI, 8)
));
double tax = 0.0800000000123;
String stax = FormatG(tax, 3);
RLOG("Formatted tax: " << stax);
RLOG("Scanned tax: " << ScanDouble(stax));
Json jtax_r("tax-rounded", roundr(tax, 2));
Json jtax_n("tax", tax);
RDUMP(jtax_r);
RDUMP(jtax_n);
Pi(2): 3.10
PI(4): 3.1420
PI(8): 3.14159270
Formatted tax: 0.08
Scanned tax: 0.08
jtax_r = {"tax-rounded":0.08}
jtax_n = {"tax":0.0800000000123}
[Edit: Code updated.]
Best regards,
Oblivion
Github page: https://github.com/ismail-yilmaz
upp-components: https://github.com/ismail-yilmaz/upp-components
Bobcat the terminal emulator: https://github.com/ismail-yilmaz/Bobcat
[Updated on: Tue, 06 September 2022 23:17] Report message to a moderator
|
|
|
Re: Value with type float [message #58810 is a reply to message #58808] |
Thu, 08 September 2022 14:49 |
jimlef
Messages: 90 Registered: September 2020 Location: US
|
Member |
|
|
Yes That would be it I'm thinking
Thank you!
Jim
Oblivion wrote on Tue, 06 September 2022 16:42Hello jimlef,
Do you mean this?
RLOG(Format(
"Pi(2): %.02f\n"
"PI(4): %.04f\n"
"PI(8): %.08f\n",
roundr(M_PI, 2),
roundr(M_PI, 4),
roundr(M_PI, 8)
));
double tax = 0.0800000000123;
String stax = FormatG(tax, 3);
RLOG("Formatted tax: " << stax);
RLOG("Scanned tax: " << ScanDouble(stax));
Json jtax_r("tax-rounded", roundr(tax, 2));
Json jtax_n("tax", tax);
RDUMP(jtax_r);
RDUMP(jtax_n);
Pi(2): 3.10
PI(4): 3.1420
PI(8): 3.14159270
Formatted tax: 0.08
Scanned tax: 0.08
jtax_r = {"tax-rounded":0.08}
jtax_n = {"tax":0.0800000000123}
[Edit: Code updated.]
Best regards,
Oblivion
|
|
|
|
Re: Value with type float [message #60198 is a reply to message #60197] |
Wed, 04 October 2023 12:08 |
Tom1
Messages: 1253 Registered: March 2007
|
Senior Contributor |
|
|
mirek wrote on Wed, 04 October 2023 10:55Just revisting this issue...
Tom1 wrote on Fri, 03 June 2022 12:03
- I can use Value with float as easily as with double without explicit type casts anywhere
Yes.
Quote:
- Assigning a float to Value reads back from Value exactly the same as it went in
If "reads back" means text output, then yes.
Quote:
- If EditFloat* is again replaced by EditDouble*, the behavior is exactly the same as it is now with EditFloat*
Should work.
Quote:
- float supports Null
No. Is that a problem?
Quote:
Maybe the precision hint you are suggesting could be automatically initialized in Value(double) / Value(float) constructors and assignment operators =(double) / =(float) to suit the assigned data type?
That was exactly the plan.
I think advantage of this solution is that it allows you to specify arbitrary precision for any double-holding Value. E.g.
double x = 3.14159;
Value json;
json("pi") = Precision(x, 2); // Precision does not exist yet
DDUMP(AsJSON(json));
Still an idea though.
Hi Mirek,
Thanks for the update on this subject.
For me 'reads back exactly the same' means binary equality:
float a = 1.234562f;
float b = 1.234562f;
Value c = b;
b = c;
if(a == b) Cout() << "Great, it works!\r\n"
else Cout() << "No, it does not read back the same...\r\n";
As for float Null, yes, please include the changes shown in:
https://www.ultimatepp.org/forums/index.php?t=msg&th=120 82&goto=59874&#msg_59874
Best regards,
Tom
|
|
|
Re: Value with type float [message #60200 is a reply to message #60198] |
Fri, 06 October 2023 12:51 |
|
mirek
Messages: 14113 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Wed, 04 October 2023 12:08mirek wrote on Wed, 04 October 2023 10:55Just revisting this issue...
Tom1 wrote on Fri, 03 June 2022 12:03
- I can use Value with float as easily as with double without explicit type casts anywhere
Yes.
Quote:
- Assigning a float to Value reads back from Value exactly the same as it went in
If "reads back" means text output, then yes.
Quote:
- If EditFloat* is again replaced by EditDouble*, the behavior is exactly the same as it is now with EditFloat*
Should work.
Quote:
- float supports Null
No. Is that a problem?
Quote:
Maybe the precision hint you are suggesting could be automatically initialized in Value(double) / Value(float) constructors and assignment operators =(double) / =(float) to suit the assigned data type?
That was exactly the plan.
I think advantage of this solution is that it allows you to specify arbitrary precision for any double-holding Value. E.g.
double x = 3.14159;
Value json;
json("pi") = Precision(x, 2); // Precision does not exist yet
DDUMP(AsJSON(json));
Still an idea though.
Hi Mirek,
Thanks for the update on this subject.
For me 'reads back exactly the same' means binary equality:
float a = 1.234562f;
float b = 1.234562f;
Value c = b;
b = c;
if(a == b) Cout() << "Great, it works!\r\n"
else Cout() << "No, it does not read back the same...\r\n";
This works (and I believe it should) right now. Am I missing something?
Quote:
As for float Null, yes, please include the changes shown in:
https://www.ultimatepp.org/forums/index.php?t=msg&th=120 82&goto=59874&#msg_59874
I am reluctant adding yet another Null...
Mirek
|
|
|
Re: Value with type float [message #60201 is a reply to message #60200] |
Fri, 06 October 2023 13:40 |
Tom1
Messages: 1253 Registered: March 2007
|
Senior Contributor |
|
|
mirek wrote on Fri, 06 October 2023 13:51This works (and I believe it should) right now. Am I missing something?
Quote:
As for float Null, yes, please include the changes shown in:
https://www.ultimatepp.org/forums/index.php?t=msg&th=120 82&goto=59874&#msg_59874
I am reluctant adding yet another Null...
Mirek
Hi Mirek,
No, you're not missing anything here. My code was there just to demonstrate what I mean by 'reads back exactly the same'.
As for the float Null: Instead of writing this:
float f = (float)(double)Null;
...
Cout() << IsNull((double)f) << "\r\n";
I would like to do this:
float f = Null;
...
Cout() << IsNull(f) << "\r\n";
Is there a specific reason why you wish to avoid adding another Null to support float?
Best regards,
Tom
|
|
|
|
Re: Value with type float [message #60203 is a reply to message #60202] |
Fri, 06 October 2023 14:28 |
Tom1
Messages: 1253 Registered: March 2007
|
Senior Contributor |
|
|
Yes, for storage space, RAM space, disk bandwidth (for speed), memory bandwidth (for speed), CPU cache space (for speed), ... I use floats all the time for any large data sets where float's accuracy is sufficient. It really pays off. Also, I mark missing data/observations using '(float)(double)Null' to handle the situation properly. And thanks to your efforts float edit fields, these days it is also handy to pull the float observations directly to dialogs for editing.
I think float is and will still remain very much alive. But if your reluctance results in refusal, I will have to keep working around this issue. That would be a pity since, after all, it is just three more lines of code in Core/Defs.h.
Best regards,
Tom
|
|
|
|
Re: Value with type float [message #60274 is a reply to message #60273] |
Mon, 30 October 2023 12:27 |
Tom1
Messages: 1253 Registered: March 2007
|
Senior Contributor |
|
|
mirek wrote on Mon, 30 October 2023 11:34OK, float support (very hesitantly and conditionally) added.
https://github.com/ultimatepp/ultimatepp/blob/cb32981c04d35f 061c0d700dac26e0fe546d36a7/autotest/Float/main.cpp
Some other tests I should add?
Hi Mirek,
Thank you very, very much! Actually, the float Value support is even wider than I would have imagined... but very much appreciated.
No other tests come to mind.
BTW: What are the conditions and consequences of your hesitation you're referring to above?
Thanks and best regards,
Tom
EDIT: PS. In Core/Value.cpp, is it intentional or a mistake to have different return typecast for float in GetOtherInt(), GetOtherInt64(), GetOtherBool() and GetOtherDouble()?
[Updated on: Mon, 30 October 2023 12:47] Report message to a moderator
|
|
|
Re: Value with type float [message #60276 is a reply to message #60274] |
Mon, 30 October 2023 13:37 |
|
mirek
Messages: 14113 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Mon, 30 October 2023 12:27mirek wrote on Mon, 30 October 2023 11:34OK, float support (very hesitantly and conditionally) added.
https://github.com/ultimatepp/ultimatepp/blob/cb32981c04d35f 061c0d700dac26e0fe546d36a7/autotest/Float/main.cpp
Some other tests I should add?
Hi Mirek,
Thank you very, very much! Actually, the float Value support is even wider than I would have imagined... but very much appreciated.
No other tests come to mind.
BTW: What are the conditions and consequences of your hesitation you're referring to above?
If it breaks something, I rollback. But frankly it is unlikely.
Quote:
EDIT: PS. In Core/Value.cpp, is it intentional or a mistake to have different return typecast for float in GetOtherInt(), GetOtherInt64(), GetOtherBool() and GetOtherDouble()?
Thanks, fixed (it was harmless, but anyway).
|
|
|
Goto Forum:
Current Time: Mon Nov 11 18:21:51 CET 2024
Total time taken to generate the page: 0.03530 seconds
|
|
|