Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 ... 483 484 [485] 486 487 ... 796

Author Topic: if self.isCoder(): post() #Programming Thread  (Read 909175 times)

miauw62

  • Bay Watcher
  • Every time you get ahead / it's just another hit
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #7260 on: April 24, 2015, 03:58:40 pm »

you can just pass the size as a parameter, or make a struct/basic class to pass all the values and data together. There's a lot you can do before considering templatizing all your functions for basic stuff.
2D arrays are passed as type array[]
  • , which is fixed at compiletime. You can just do this "manually" with a 1D array to make it act like a 2D array, but that's not ideal either.
Logged

Quote from: NW_Kohaku
they wouldn't be able to tell the difference between the raving confessions of a mass murdering cannibal from a recipe to bake a pie.
Knowing Belgium, everyone will vote for themselves out of mistrust for anyone else, and some kind of weird direct democracy coalition will need to be formed from 11 million or so individuals.

Reelya

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #7261 on: April 24, 2015, 04:48:05 pm »

The best solution is what I said earlier. Make a minimal wrapper class that just has a data pointer, x and y size, a constructor to make the data, destructor to free the memory, and an [] operator which takes x and y parameters, and returns a reference. You might want to make the data type itself a template though, so that the code can be reused for different data types.

There's no need to templatize the function that the array is passed to, and that would mean you couldn't change the size of the array at runtime, since template parameters need to be constants. By wrapping the data in a simple class, you get the ability to pass around arbitrary-sized 2D arrays.
« Last Edit: April 24, 2015, 04:56:41 pm by Reelya »
Logged

Gentlefish

  • Bay Watcher
  • [PREFSTRING: balloon-like qualities]
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #7262 on: April 24, 2015, 08:18:21 pm »

you can just pass the size as a parameter, or make a struct/basic class to pass all the values and data together. There's a lot you can do before considering templatizing all your functions for basic stuff.
2D arrays are passed as
Code: [Select]
type array[][x], which is fixed at compiletime. You can just do this "manually" with a 1D array to make it act like a 2D array, but that's not ideal either.

There you go. Today I learned a neat BBC line!

alway

  • Bay Watcher
  • 🏳️‍⚧️
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #7263 on: April 25, 2015, 12:34:21 am »

Added a second graphics tutorial code thing here: https://github.com/jalway/tut2
Actual OpenGL in this one, though you can hardly tell the difference. It's 3D rendering, with the object in question generated in the shader, like with the previous one. Unfortunately, the 3D transformation matrices are mostly unexplained (I figured they were covered in one of the other tutorials being put together, but they don't seem to be, so that will be addressed in future stuff), but there's a variety of interesting tidbits in the vertex shader. Again, feedback's always welcome on these, since the end goal is to subject students and such to them.
Logged

miauw62

  • Bay Watcher
  • Every time you get ahead / it's just another hit
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #7264 on: April 25, 2015, 03:31:06 am »

The best solution is what I said earlier. Make a minimal wrapper class that just has a data pointer, x and y size, a constructor to make the data, destructor to free the memory, and an [] operator which takes x and y parameters, and returns a reference. You might want to make the data type itself a template though, so that the code can be reused for different data types.

There's no need to templatize the function that the array is passed to, and that would mean you couldn't change the size of the array at runtime, since template parameters need to be constants. By wrapping the data in a simple class, you get the ability to pass around arbitrary-sized 2D arrays.
Once you have implemented what you said, how different is it from a vector<vector<>>? (especially if you use push_back() sparingly)
I guess you could also have a function to change XY coords into the position on the array, (array[function(X, Y, Xsize, Ysize)]), although the size would still be fixed on compiletime.
But yeah you're right about the function templates.
Logged

Quote from: NW_Kohaku
they wouldn't be able to tell the difference between the raving confessions of a mass murdering cannibal from a recipe to bake a pie.
Knowing Belgium, everyone will vote for themselves out of mistrust for anyone else, and some kind of weird direct democracy coalition will need to be formed from 11 million or so individuals.

Reelya

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #7265 on: April 25, 2015, 04:12:04 am »

It's a hell of a lot different from a vector<vector>. With a vector of vectors you have to do a lot more work to get the context right of it being a 2D array, for loops (either explicit or implicit) to size all the inner vectors and everything.

The code for a simple custom 2D array wrapper is just this:

Code: [Select]
template <class T> class grid
{
    T *data;
public:
    int sizex, sizey;

    grid(int _sizex, int _sizey) : sizex(_sizex), sizey(_sizey)
    {
        data = new T[sizex * sizey];
    }

    ~grid() { delete [] data; }

    T &operator[](int x, int y) { return data[x + sizex * y]; }
}

// usage:
grid<char> charArray2D(20,20);

There you go, a fully encapsulated 2D array that can be sized at runtime, and passed as a single parameter, no bullshit or complexity. It's templatized, but the actual code is so minimal that it won't really bloat much if you make 2D arrays of different types. You can add optional bounds-checking inside the class, but have the advantage of being able to turn it off for higher speed, if you've sufficiently debugged the rest of your program.

with vector<vector> it's already instantiating two copies of the vector class and everything that goes with it, (vector<thing> and vector<vector<thing>>) including cloning the iterator types. Then, accessing the vector is a matter of chaining the calls through the methods of the two separate vector classes, so that's more runtime overhead.
« Last Edit: April 25, 2015, 04:31:11 am by Reelya »
Logged

miauw62

  • Bay Watcher
  • Every time you get ahead / it's just another hit
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #7266 on: April 25, 2015, 05:24:13 am »

Fair enough. I do as I said, though, "pure" 2D arrays are butt.

E:
what was i thinking when i wrote "i do as i said"
« Last Edit: April 25, 2015, 05:40:57 am by miauw62 »
Logged

Quote from: NW_Kohaku
they wouldn't be able to tell the difference between the raving confessions of a mass murdering cannibal from a recipe to bake a pie.
Knowing Belgium, everyone will vote for themselves out of mistrust for anyone else, and some kind of weird direct democracy coalition will need to be formed from 11 million or so individuals.

MorleyDev

  • Bay Watcher
  • "It is not enough for it to just work."
    • View Profile
    • MorleyDev
Re: if self.isCoder(): post() #Programming Thread
« Reply #7267 on: April 25, 2015, 05:24:32 am »

The 'single vector' approach also minimises cache misses when iterating through a grid. Vectors are continuous blocks of memory, but there vectors in a vector-of-vectors will be dotted around the heap, so iterating causes cache misses (this is why std::list is slower to iterate) 

Arguing like this may seem like a premature optimisation, but using a single vector like above is also a simpler and cleaner solution than using a vector of vectors (when the size of the grid doesn't need to change after it's been created). It's a recurring trend I've noticed in software that most of the time, the simplest/cleanest solution is also the one most likely to be the one that is efficient enough. Especially with the current state of the optimisations compilers can make nowadays.
« Last Edit: April 25, 2015, 06:29:52 am by MorleyDev »
Logged

Reelya

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #7268 on: April 25, 2015, 05:31:21 am »

Hiding things behind wrappers can be a good idea, especially if "premature optimization" is under debate. Wrap the quick and dirty method up behind a wrapper class or function. This gives you the best isolation of client-side and implementation-side code. Ideally, the client code shouldn't know whether it's implemented my way, or by a vector of vectors.

If you're using a library, designing your code to use wrappers from the start can be a very good idea. Rather than including the .h file for the library everywhere, include it in a .cpp file, then give that .cpp file a .h file which contains functions that pass calls to the library. Presto, you've isolated library calls to that one .cpp file, which helps if you want to change to a new library later. With this approach thinking something like "We support OpenGL but wouldn't it be good to support Direct3D too?" goes from nearly impossible to quite achievable. Compare that to a situation where you have raw OpenGL calls scattered amongst dozen of places in the progam. The "straightforward" solution to that would be to put if/then or #ifdefs around every single library call in every cpp file.
« Last Edit: April 25, 2015, 05:38:48 am by Reelya »
Logged

alway

  • Bay Watcher
  • 🏳️‍⚧️
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #7269 on: April 25, 2015, 01:37:34 pm »

Taking a free 20x speedup isn't premature optimization, that's simply not being daft. Aside from that, a vector of vectors isn't an nxn grid. It's n arrays of lengths o,p,q,r,s,t... etc; after all, each element of the vector of vectors is itself a vector, which could be anything.

And yes, simpler code is usually better code. If your code is doing less... then that means your code is doing less. Which is obviously a good thing in terms of performance.

However, I would warn somewhat about wrapper classes. I recommend doing without them initially, and only introducing them after you've used the systems enough that the patterns of use become obvious to you. It's really easy to put a wrapper around something which partially obscures the implementation details which would have helped you if you put things into wrappers when still in the 'planning what to code' phase.
Logged

Gatleos

  • Bay Watcher
  • Mournhold... City of Light... City of MAGIC!
    • View Profile
    • Someone Sig This
Re: if self.isCoder(): post() #Programming Thread
« Reply #7270 on: April 25, 2015, 02:16:53 pm »

Did someone say 2D Arrays?

I made that a while back. I was actually going to post it here for advice on improving it. It's the first time I've made a custom iterator or elaborate template class like that, so I'm sure I messed something up.

Also 2D+ c-style arrays are evil never use them
Logged
Think of it like Sim City, except with rival mayors that seek to destroy your citizens by arming legions of homeless people and sending them to attack you.
Quote from: Moonshadow101
it would be funny to see babies spontaneously combust
Gat HQ (Sigtext)
++U+U++ // ,.,.@UUUUUUUU

TheDarkStar

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #7271 on: April 25, 2015, 09:38:02 pm »

Is there a way to use operator overloading to change what repeated brackets refer to? For example, this:

void main()
{
//blah blah blah
2DVector 2DListOfStuff;
OutVariable = 2DListOfStuff[4][5];
//output and then do other stuff
}

where 2DListOfStuff is a class that stores a single vector that holds all the values and then the [] (or [][] or whatever) operator is overloaded to access specific parts of the array. Could it work?
Logged
Don't die; it's bad for your health!

it happened it happened it happen im so hyped to actually get attacked now

Reelya

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #7272 on: April 25, 2015, 10:20:28 pm »

my last post overloads [] to take x and y values, i.e. "grid[x,y]".

repeated brackets could be emulated by overloading the first bracket to do the row, and the second bracket return the column. It's definitely do-able, and can work in parallel to the two-parameter version. But you probably want the first value to be "x" and the second value to be "y", so you want a column-centric grid rather than row-centric like normal if you want that. Usually I have a row-centric grid and put 'y' as the outside loop. This is better for caching memory reads, you want your reads to follow the flow of the data. But with a column-centric grid, i.e. [X][Y], you want to loop X as the outer variable, and Y as the inner variable.

Adapting my previous code, it would work like this

T *operator[](int x) { return &data[x * sizey]; }

This returns a 'T" pointer, pointing at the memory location of the top of the requested column. Then, a second [] is used to look up the cell in that column, using c++'s normal pointer dereferencing. I modified my code below so that it will now work with either [X,Y] or [X][Y] addressing.

Spoiler (click to show/hide)
« Last Edit: April 25, 2015, 10:27:38 pm by Reelya »
Logged

Skyrunner

  • Bay Watcher
  • ?!?!
    • View Profile
    • Portfolio
Re: if self.isCoder(): post() #Programming Thread
« Reply #7273 on: April 26, 2015, 05:02:52 am »

C++17 to have modules! Hype :v
Logged

bay12 lower boards IRC:irc.darkmyst.org @ #bay12lb
"Oh, they never lie. They dissemble, evade, prevaricate, confoud, confuse, distract, obscure, subtly misrepresent and willfully misunderstand with what often appears to be a positively gleeful relish ... but they never lie" -- Look To Windward

Putnam

  • Bay Watcher
  • DAT WIZARD
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #7274 on: April 26, 2015, 05:17:31 am »

haha FUCK header files

Quote
parallel algorithms (incl. parallel versions of some of the STL)
Simplify core language use, especially as it relates to the STL and concurrency, and address major sources of errors.

maybe people will stop whining to Toady about multi-threading :V
« Last Edit: April 26, 2015, 05:20:46 am by Putnam »
Logged
Pages: 1 ... 483 484 [485] 486 487 ... 796