Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Impotence
Nov 8, 2010
Lipstick Apathy
I already use Spring on Java 8.

Adbot
ADBOT LOVES YOU

Soricidus
Oct 21, 2010
freedom-hating statist shill

Ola posted:

What if I told you you could gather all your technical debt into one easy framework?

Thread title potential

ephphatha
Dec 18, 2009




Biowarfare posted:

I already use Spring on Java 8.

:negative: why you gotta call me out like this

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...

Soricidus posted:

Thread title potential

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?

Soricidus posted:

Thread title potential

The current one is getting old

Absurd Alhazred
Mar 27, 2010

by Athanatos
Technical debt consolidation

fritz
Jul 26, 2003

Doom Mathematic posted:

Yes, this is called a ground-up rewrite.

Should only be considered if you're feeling pretty ground-up already.

Mega Comrade
Apr 22, 2004

Listen buddy, we all got problems!
Just been given a spec where a 3rd part wants an api endpoint that accepts a xml body as the post, which is 'fine' I suppose. Its a standard all element based request, easy enough to parse.

But they want the response to be a single element with all the results as a list of attributes and no sub elements within it...

toiletbrush
May 17, 2010

Mega Comrade posted:

Just been given a spec where a 3rd part wants an api endpoint that accepts a xml body as the post, which is 'fine' I suppose. Its a standard all element based request, easy enough to parse.

But they want the response to be a single element with all the results as a list of attributes and no sub elements within it...
they've written their own parser, haven't they

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
My guess is they concatenate it into a larger document and then parse it. Stick an opening cdata at the end of the response and see what happens.

Impotence
Nov 8, 2010
Lipstick Apathy
they are parsing it with regex

Hughmoris
Apr 21, 2007
Let's go to the abyss!

Biowarfare posted:

they are parsing it with regex

The <center> cannot hold it is too late.

Xarn
Jun 26, 2015
I wrote this yesterday

C++ code:
if (lhs == 0) {
  lhs = 0;
}
the funny part is that this is exactly what I wanted write, and is correct. :v:



(Yeah, later I changed it to be clearer)

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

Xarn posted:

I wrote this yesterday

C++ code:
if (lhs == 0) {
  lhs = 0;
}
the funny part is that this is exactly what I wanted write, and is correct. :v:



(Yeah, later I changed it to be clearer)

I'm afraid to ask, what made this code different from a noop?

(I mean in your specific real case, I know that theoretically those operators can be overloaded etc.)

Xarn
Jun 26, 2015
As a hint, here is the second version (without comments, and the final version does some further trickery, because it is wrapped in a template)

C++ code:
if (lhs == 0.) {
  lhs = 0.;
}

Van Kraken
Feb 13, 2012

Xarn posted:

As a hint, here is the second version (without comments, and the final version does some further trickery, because it is wrapped in a template)

C++ code:
if (lhs == 0.) {
  lhs = 0.;
}

Replacing negative 0 with regular 0?

Tei
Feb 19, 2011

== 0. could result on floating point errors, I guess.. it may also creating visual errors like z-fighting on 3d engines, I guess.

double vs single precission could result on round errors. "Everybody" expect the result on a calculation match their excel page, and if not, is a error.

Xarn
Jun 26, 2015

Van Kraken posted:

Replacing negative 0 with regular 0?

Yup. It's followed by some terrible bitwise fuckery that relies on IEEE floats and zeros having positive zero representation.

Absurd Alhazred
Mar 27, 2010

by Athanatos
Floating point is of the devil.

Doom Mathematic
Sep 2, 2008
Is there no way to explicitly test for negative zero?

Beef
Jul 26, 2004

Xarn posted:

Yup. It's followed by some terrible bitwise fuckery that relies on IEEE floats and zeros having positive zero representation.

I think you posted the wrong horror.

I would blow Dane Cook
Dec 26, 2008
There’s a negative zero?

Foxfire_
Nov 8, 2010

Xarn posted:

Yup. It's followed by some terrible bitwise fuckery that relies on IEEE floats and zeros having positive zero representation.

Is your compiler obligated to replace it? I wouldn't be surprised if a compiler (rightly or wrongly) deletes that in high optimization levels.

I would blow Dane Cook posted:

There’s a negative zero?
IEE754 uses a sign bit, so there's two zero patterns. They also do some stuff behaviorally different about whether you get + or - inf in some operations

Xerophyte
Mar 17, 2008

This space intentionally left blank

Doom Mathematic posted:

Is there no way to explicitly test for negative zero?

Looks like
C++ code:
std::fpclassify(x) == FP_ZERO && std::signbit(x)
is as good as it gets in c or cpp-land, assuming this is c or cpp-land. Negative zero is not its own classification. I guess you could write the == 0.0 test with fpclassify if you really wanted to and felt it clarified things. The compiler should emit the same code either way.

Less portably, you can always memcpy (or Double.doubleToLongBits or whatever your local language equivalent is) and test the bits against the bits of -0.0 -- presumably 0x1<<63. This seems to be somewhat faster but, on the other hand, bits are smelly and dirty.


I would blow Dane Cook posted:

There’s a negative zero?

IEEE 754 is a gift that keeps on giving. Wait until you find out about subnormals and quiet vs signaling NaNs!


E:

Foxfire_ posted:

Is your compiler obligated to replace it? I wouldn't be surprised if a compiler (rightly or wrongly) deletes that in high optimization levels.

It's definitely obligated by IEEE 754, the two different zeros should explicitly compare as equal.

You can of course set -fno-signed-zeros or your local equivalent, which does a lot of fun things that the IEEE would frown at but should not, I think, change the basic comparison behavior for zeros. Setting it just means the compiler doesn't try to correctly preserve the sign. Code that in strict compliance should have produced negative zero can instead produce positive zero, or vice versa. For instance no-signed-zeros allows the compiler to assume that 0.0 - x == -x when simplifying expressions, even though this is not strictly correct for x = 0.0 and would in that case produce an incorrect -0.0. All the -ffast-math flags are mostly about relaxing IEEE strictness to allow for more arithmetic transforms.

A compiler unilaterally assuming that zero has a single bit representation in IEEE floating point would probably break a lot of things since neither the underlying instructions or typical calling code will behave like that. Still, I'm sure someone somewhere has hosed it up at some point. It's how these things go.

Xerophyte fucked around with this message at 00:13 on Jul 26, 2021

Doom Mathematic
Sep 2, 2008

Xerophyte posted:

Looks like
C++ code:
std::fpclassify(x) == FP_ZERO && std::signbit(x)
is as good as it gets in c or cpp-land, assuming this is c or cpp-land. Negative zero is not its own classification. I guess you could write the == 0.0 test with fpclassify if you really wanted to and felt it clarified things. The compiler should emit the same code either way.

My concern is less what the compiler emits and more someone coming along later and removing a piece of code they perceive to be a no-op. In JavaScript we have Object.is(x, -0). Before we had that, we used 1 / x === -Infinity. Failing something like that, I guess I would settle for an explanatory comment...

Bongo Bill
Jan 17, 2012

Doom Mathematic posted:

My concern is less what the compiler emits and more someone coming along later and removing a piece of code they perceive to be a no-op. In JavaScript we have Object.is(x, -0). Before we had that, we used 1 / x === -Infinity. Failing something like that, I guess I would settle for an explanatory comment...

Use a unit test for this.

Zopotantor
Feb 24, 2013

...und ist er drin dann lassen wir ihn niemals wieder raus...

I would blow Dane Cook posted:

There’s a negative zero?

Yup. It's useful in some situations (e.g., for representing branch cuts of various complex functions), but IIRC no language in the C family makes use of that.

CPColin
Sep 9, 2003

Big ol' smile.

Van Kraken posted:

Replacing negative 0 with regular 0?

Only registered members can see post attachments!

Xarn
Jun 26, 2015

Beef posted:

I think you posted the wrong horror.

Nah, that's actually beautiful code :v:

C++ code:
    template <typename FP>
    uint64_t ulpDistance( FP lhs, FP rhs ) {
        assert( std::numeric_limits<FP>::is_iec559 &&
            "ulpDistance assumes IEEE-754 format for floating point types" );
        assert( !Catch::isnan( lhs ) &&
                "Distance between NaN and number is not meaningful" );
        assert( !Catch::isnan( rhs ) &&
                "Distance between NaN and number is not meaningful" );

        // We want X == Y to imply 0 ULP distance even if X and Y aren't
        // bit-equal (-0 and 0), or X - Y != 0 (same sign infinities).
        if ( lhs == rhs ) { return 0; }

        // We need a properly typed positive zero for type inference.
        static constexpr FP positive_zero{};

        // We want to ensure that +/- 0 is always represented as positive zero
        if ( lhs == positive_zero ) { lhs = positive_zero; }
        if ( rhs == positive_zero ) { rhs = positive_zero; }

        // If arguments have different signs, we can handle them by summing
        // how far are they from 0 each.
        if ( ( lhs < 0 ) != ( rhs < 0 ) ) {
            return ulpDistance( std::abs( lhs ), positive_zero ) +
                   ulpDistance( std::abs( rhs ), positive_zero );
        }

        // When both lhs and rhs are of the same sign, we can just
        // read the numbers bitwise as integers, and then subtract them
        // (assuming IEEE).
        uint64_t lc = Detail::convertToBits( lhs );
        uint64_t rc = Detail::convertToBits( rhs );

        // The ulp distance between two numbers is symmetric, so to avoid
        // dealing with overflows we want the bigger converted number on the lhs
        if ( lc < rc ) {
            std::swap( lc, rc );
        }

        return lc - rc;
    }

DELETE CASCADE
Oct 25, 2017

i haven't washed my penis since i jerked it to a phtotograph of george w. bush in 2003

Xarn posted:

Nah, that's actually beautiful code :v:

C++ code:
    template <typename FP>
    uint64_t ulpDistance( FP lhs, FP rhs ) {
        assert( std::numeric_limits<FP>::is_iec559 &&
            "ulpDistance assumes IEEE-754 format for floating point types" );
        assert( !Catch::isnan( lhs ) &&
                "Distance between NaN and number is not meaningful" );
        assert( !Catch::isnan( rhs ) &&
                "Distance between NaN and number is not meaningful" );

        // We want X == Y to imply 0 ULP distance even if X and Y aren't
        // bit-equal (-0 and 0), or X - Y != 0 (same sign infinities).
        if ( lhs == rhs ) { return 0; }

        // We need a properly typed positive zero for type inference.
        static constexpr FP positive_zero{};

        // We want to ensure that +/- 0 is always represented as positive zero
        if ( lhs == positive_zero ) { lhs = positive_zero; }
        if ( rhs == positive_zero ) { rhs = positive_zero; }

        // If arguments have different signs, we can handle them by summing
        // how far are they from 0 each.
        if ( ( lhs < 0 ) != ( rhs < 0 ) ) {
            return ulpDistance( std::abs( lhs ), positive_zero ) +
                   ulpDistance( std::abs( rhs ), positive_zero );
        }

        // When both lhs and rhs are of the same sign, we can just
        // read the numbers bitwise as integers, and then subtract them
        // (assuming IEEE).
        uint64_t lc = Detail::convertToBits( lhs );
        uint64_t rc = Detail::convertToBits( rhs );

        // The ulp distance between two numbers is symmetric, so to avoid
        // dealing with overflows we want the bigger converted number on the lhs
        if ( lc < rc ) {
            std::swap( lc, rc );
        }

        return lc - rc;
    }

if you think this is beautiful, you got a serious case of c++ brain

bobthenameless
Jun 20, 2005

It seems cool to me, clean for what it is

Tei
Feb 19, 2011

- Defining that whateveristhis as FP. I don't know what F.P. is, it mean something but is imposible to say from the name. This is caused by the need to use the FP name often, so the programmer tried to make it short. He had to choice between making the code obscure or verbose, and choosed obscure.

- Prefix like "ulp". Again, is imposible to know what "ulp" means. A name is like ulpDistance is obscure. It could be again the choice between obscure or verbose was made to obscure.

- if ( ( lhs < 0 ) != ( rhs < 0 ) ) {. you don't need all these "(" and ")" guy.

- uint64_t is ugly, but compact. it result on code like this:
uint64_t lc = Detail::convertToBits( lhs );

this could have been looker better like this:

unsigned int64 lc;
...
lc = Detail::convertToBits( lhs );

I guess you are forced to use uint64_t to make sure is a 64 bits integer and not any other word size.

At not point is declared the return type.

I would be better with doxygen type comments
/**
*
...
* @return uint64_t delta
* /

or by having the language define the return type
unsigned int64 Distance( floatingpoint lhs, floatingpoint rhs ): unsigned int64 {

I guess this would look better for people that hate verbose code:
uint64 Distance( floatingpoint lhs, floatingpoint rhs ): uint64 {

I would have another function with the same name if neccesary

uint64 Distance( int l, int r ): uint64 {

let the compiler choose the right one based on the type of the input

----

std::abs( lhs )

A language with namesspaces can do this:

use std::abs as abs;

then use abs withouth specifing

abs( lhs )

----

About this:
return ulpDistance( std::abs( lhs ), positive_zero ) +
ulpDistance( std::abs( rhs ), positive_zero );

I would have a alias "self" that would always point to the current function or method.

return self( abs( lhs ), positive_zero ) + self( abs( rhs ), positive_zero );

why? so is easy to refactor and because not everything that can have a name need to have a name.


C++ code:
    use std::abs as abs;
    use std:swap as swap;
    use std:numeric_llimits as numeric_limits;    

    template <typename floatingPoint>
    uint64 ulpDistance( floatingPoint lhs, floatingPoint rhs ): uint64 {
        assert( numeric_limits<floatingPoint>::is_iec559 &&
            "ulpDistance assumes IEEE-754 format for floating point types" );
        assert( !Catch::isnan( lhs ) &&
                "Distance between NaN and number is not meaningful" );
        assert( !Catch::isnan( rhs ) &&
                "Distance between NaN and number is not meaningful" );

        // We want X == Y to imply 0 ULP distance even if X and Y aren't
        // bit-equal (-0 and 0), or X - Y != 0 (same sign infinities).
        if ( lhs == rhs ) { return 0; }

        // We need a properly typed positive zero for type inference.
        static constexpr FP positive_zero{};

        // We want to ensure that +/- 0 is always represented as positive zero
        if ( lhs == positive_zero ) { lhs = positive_zero; }
        if ( rhs == positive_zero ) { rhs = positive_zero; }

        // If arguments have different signs, we can handle them by summing
        // how far are they from 0 each.
        if ( ( lhs < 0 ) != ( rhs < 0 ) ) {
            return self( abs( lhs ), positive_zero ) +. self( abs( rhs ), positive_zero );
        }

       uint64 lc, rc;

        // When both lhs and rhs are of the same sign, we can just
        // read the numbers bitwise as integers, and then subtract them
        // (assuming IEEE).
        lc = Detail::convertToBits( lhs );
        rc = Detail::convertToBits( rhs );

        // The ulp distance between two numbers is symmetric, so to avoid
        // dealing with overflows we want the bigger converted number on the lhs
        return ( lc < rc )?  swap( lc, rc ):  lc - rc;        
    }
sorry for the use of ?: at the end, I can't stop myself.

Tei fucked around with this message at 08:01 on Jul 27, 2021

Qwertycoatl
Dec 31, 2008

I don't think that function benefits from either being made incorrect or from using a language feature that doesn't exist. YMMV I suppose.

Sagacity
May 2, 2003
Hopefully my epitaph will be funnier than my custom title.

Tei posted:

"advice"
fry-not-sure-if-sarcastic.jpg

Athas
Aug 6, 2007

fuck that joker

Tei posted:

- Prefix like "ulp". Again, is imposible to know what "ulp" means. A name is like ulpDistance is obscure. It could be again the choice between obscure or verbose was made to obscure.

Why would someone who doesn't know what a ulp is care about this function at all? They certainly should not modify it. It's definitely OK that domain code uses domain terms, and this code is fine (except for superficial but unavoidable C++ syntax stuff).

I hope I got trolled.

Tei
Feb 19, 2011

Qwertycoatl posted:

I don't think that function benefits from either being made incorrect or from using a language feature that doesn't exist. YMMV I suppose.

C++ was created by people that trough C syntax was kind of lacking

My comment was in the line "if this is the best looking C++ code you can make, C++ is lacking".

toiletbrush
May 17, 2010

Athas posted:

Why would someone who doesn't know what a ulp is care about this function at all? They certainly should not modify it. It's definitely OK that domain code uses domain terms, and this code is fine (except for superficial but unavoidable C++ syntax stuff).

I hope I got trolled.
yeah, ulp is a term of art that anyone who had to understand this code would already know, like accounting software having a variable called 'vatAmount'

'new junior dev takes team lead down a notch or two with scathing PR feedback'

nielsm
Jun 1, 2009




At least put some effort into learning C++ if you're going to troll about it.

uint64 is not a standard type name in C or C++, uint64_t is. If you wanted to use a keywords-only type that in most implementations end up as a 64 bit unsigned integer then unsigned long long would be the way to go.
(Reference: https://en.cppreference.com/w/cpp/types/integer)

Convention is to CamelCase template parameter names, if you don't just shorten them to one or two letters. When it's obviously just the type of the parameter the function/class works on, a one or two letter name is accepted, with T being common.

You're technically right on the operator precedence of (lhs < 0 != rhs < 0) but I'd say it's one of those cases where you can't expect programmers to remember the exact rules. Personally I'd prefer this written as (std::signbit(lhs) != std::signbit(rhs)), to make the expression explicitly read as "the left and right hand sides have different sign".

The syntax for renaming types/importing from a namespace is using abs = std::abs;
(Reference: https://en.cppreference.com/w/cpp/language/type_alias)

Carbon dioxide
Oct 9, 2012

Can we list the crimes of Eich?

- Said masks and lockdowns don't work and that Fauci "lies a lot"
- Invented a cryptocurrency
- Is against same-sex marriage
- Invented Javascript

I'm not sure which of these is the worst.

Adbot
ADBOT LOVES YOU

Spatial
Nov 15, 2007

This is so terrible, it's like human clippy giving C++ advice

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply