Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Very large company values are not graphed correctly #8253

Open
James103 opened this issue Jul 2, 2020 · 2 comments
Open

Very large company values are not graphed correctly #8253

James103 opened this issue Jul 2, 2020 · 2 comments
Labels
bug

Comments

@James103
Copy link
Contributor

@James103 James103 commented Jul 2, 2020

Version of OpenTTD

master (2020-07-01)

Expected result

  • Company value of 2^63-1 is recorded on the company value graph.
  • Company value of e.g. 2^63-10000 is recorded on the company value graph, with data points being visible.
  • The scale in these cases runs from 0 to 2^63-1.

Actual result

  • Company value of 2^63-1 is not recorded on the company value graph at all (scale still runs from -5 to 4).
    image

  • Company value of e.g. 2^63-10000 is still recorded on the company value graph, but the points do not appear.
    image

  • The scale runs from 0 to (2^63-1)/10 (~922 billion million) instead of from 0 to 2^63-1 (~9.22 trillion million).
    (see above images)

Steps to reproduce

  1. Load the attached savegame.
  2. Fast forward a few years. The money (and company value) will max out.
  3. Open the company value graph. It appears blank.
  4. Open your company finances window, and hit the "Borrow £10,000" button a couple of times.
  5. Fast forward a few months.
  6. Take a look at the company info window and company value graph.
  7. Hit the "Repay £10,000" button until the loan has been repaid.
  8. Take a look at the company info window and company value graph.

Savegame

Gronnway Transport, 363576-09-15.zip
(The savegame contains a single company with maxed-out (2^63-1) company value and cash, and has been optimized to run at up to several in-game years per second on high-end modern hardware.)

@TrueBrain
Copy link
Member

@TrueBrain TrueBrain commented Jan 1, 2021

You are an absolute madman to make a savegame for this and clear steps to reproduce :D Awesome, tnx :)

@TrueBrain TrueBrain added the bug label Jan 1, 2021
@LordAro
Copy link
Member

@LordAro LordAro commented Jul 19, 2021

The first part's quite fun - the graphing code uses INT64_MAX as "INVALID_DATAPOINT" . Of course, if it actually gets that value, it just ignores all the data.

static const OverflowSafeInt64 INVALID_DATAPOINT(INT64_MAX); // Value used for a datapoint that shouldn't be drawn.

A hacky fix might be to use INT64_MIN as a sentinel value, but I'd say that in real world conditions one is no less likely to appear than the other, so probably wouldn't actually fix anything

I'm not quite sure about the second issue. The y value that it's trying to draw the datapoint at is a very small negative number. I suspect it has something to do with the bitshifting of the very large datapoints to create the "x million" value

OpenTTD/src/graph_gui.cpp

Lines 437 to 457 in 1e529e1

/*
* Check whether we need to reduce the 'accuracy' of the
* datapoint value and the highest value to split overflows.
* And when 'drawing' 'one million' or 'one million and one'
* there is no significant difference, so the least
* significant bits can just be removed.
*
* If there are more bits needed than would fit in a 32 bits
* integer, so at about 31 bits because of the sign bit, the
* least significant bits are removed.
*/
int mult_range = FindLastBit(x_axis_offset) + FindLastBit(abs(datapoint));
int reduce_range = std::max(mult_range - 31, 0);
/* Handle negative values differently (don't shift sign) */
if (datapoint < 0) {
datapoint = -(abs(datapoint) >> reduce_range);
} else {
datapoint >>= reduce_range;
}
y = r.top + x_axis_offset - ((r.bottom - r.top) * datapoint) / (interval_size >> reduce_range);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug
Projects
None yet
Development

No branches or pull requests

3 participants