![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Andrew C on Mozilla <voi### [at] dev null> wrote:
> Question: what IS the issue? (Maybe I'm just slow...)
If I'm not completely mistaken, I think that the basic issue here
is which OO properties POV-Ray's scripting language would benefit from
and which would be unnecessary.
--
#macro N(D)#if(D>99)cylinder{M()#local D=div(D,104);M().5,2pigment{rgb M()}}
N(D)#end#end#macro M()<mod(D,13)-6mod(div(D,13)8)-3,10>#end blob{
N(11117333955)N(4254934330)N(3900569407)N(7382340)N(3358)N(970)}// - Warp -
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
> I just gave a simple example and wanted to point out that using operator
> overloading does not add any overhead whatsoever to regular function calls.
I never said it did.
Oh dear, oh dear, I seem to have confused you. I'll try to explain:
What I said is that if you have a + between two ints it compiles to less code
than if you have a + you've defined as an overload operator *for a more complex
type*.
i.e. the code looks the same, but it does more stuff (because the data it's
operating on is more complex). This is *good* from an OO point of view, because
you don't need to know about the implementation of the object in order to use
it, but bad from an optimisation point of view, because you do need to know
about the implementation in order to be able to use it *efficiently*.
> Using operators makes the code cleaner and easier to read with complex
> expressions.
So what if it's easier to read? A good programmer can deal with code that's hard
to read, it's good if it's readable but not if you've lost some information you
might want.
> If you don't know what operator+() does with the type you are using,
> then you should seek another job, IMHO.
> If you are making speed-critical code then you should know your tools.
Right, lets say your product ships in two weeks time, and you've discovered that
the physics guy who got sacked last week was a moron. Hey, it happens. You need
to go through his code and find everywhere that he's performing a matrix*vector
multiply, in order to replace it with a more efficient piece of code.
How do you do that?
--
Tek
www.evilsuperbrain.com
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
> > Anyway, my point isn't just the function call overhead, it's the fact that
> > it's not an operator internally supported by the compiler with a bunch of
> > rules, it's a series of instructions of unspecified length elsewhere.
>
> There is no such difference.
Okay, remove the word "elsewhere" and you might see what I mean.
> > Well, it can lose the function call overhead, but not the overhead of it
being
> > a function (i.e. several instructions) rather than a simple instruction
(which
> > is really my point).
>
> No, there won't be additional instructions if a function is inlined. For
> any (not ten year old) compiler the overhead of inlining a function will be
> exactly zero compared to direct insertion of the code.
ffs, I know that! I know what inline does! I'm talking with the premise that you
won't write a function to do something you can already do in one line of code.
i.e. if anyone, anywhere, ever writes a function:
add(a,b)
{
return a+b;
}
that person should be dragged out into the street and shot*. So, ON THAT
PREMISE, if you have decided to write an inline function there will be an
"overhead of it being a function (i.e. several instructions) rather than a
simple instruction", by which I mean you have decided to write a function that
is more than one instruction.
I just explained that *really* badly yet again...
What I'm saying is, quite simply, we like to make a distinction between "+" and
any more elaborate function. Because doing so prevents people writing lines like
a = b + 3*(c-d), which looks perfectly innocent, but could be a major
bottleneck.
I'm not saying overload operators are a bad thing, I'm just presenting the
reasons why we don't generally use them in game coding. I think for simple types
which are well suited to the compiler you could define some more (like vectors),
but I'd still make a distinction between that and a significantly greater amount
of processing.
We like the clunkier syntax *because* it is harder to use and requires more
thought from the programmer. In our situation this is a good thing.
--
Tek
www.evilsuperbrain.com
*I bet someone's now going to come up with a perfectly good reason why they
might do this, but it's 5:20am and I can't think of one!
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
"Warp" <war### [at] tag povray org> wrote in message news:4038a07d@news.povray.org...
> Andrew C on Mozilla <voi### [at] dev null> wrote:
> > Question: what IS the issue? (Maybe I'm just slow...)
>
> If I'm not completely mistaken, I think that the basic issue here
> is which OO properties POV-Ray's scripting language would benefit from
> and which would be unnecessary.
Well the original issue was me saying "I want to do some OO-style pov code. Has
anyone done this before?". Although the thread seems to have drifted away from
that... :)
--
Tek
www.evilsuperbrain.com
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Tek <tek### [at] evilsuperbrain com> wrote:
> What I said is that if you have a + between two ints it compiles to less code
> than if you have a + you've defined as an overload operator *for a more complex
> type*.
Actually, that's not always so.
In my example the + between the two class instances generated no code
at all, while a + between two ints may generate an addition asm code
(when the compiler can't do it at compile time)... :)
> i.e. the code looks the same, but it does more stuff (because the data it's
> operating on is more complex). This is *good* from an OO point of view, because
> you don't need to know about the implementation of the object in order to use
> it, but bad from an optimisation point of view, because you do need to know
> about the implementation in order to be able to use it *efficiently*.
You need to know about how a library function is implemented anyways,
regardless of how it is called, if you want to make as optimal code as
possible.
If you are using class instances you know that calling the operator+
for them will (potentially) generate a function call. If you don't know
that, you don't have business making highly-optimized hacker code.
Besides, it's true what they say that optimization should firstly be
made at algorithmical level. Only when the algorithms and data containers
are as efficient as possible and the code still is too slow, then one should
try to look what is taking so long.
Optimizing a function call away won't help you if your algorithm is
a thousand times slower than a completely different algorithm which makes
the same thing. :)
> > Using operators makes the code cleaner and easier to read with complex
> > expressions.
> So what if it's easier to read?
If you make write-and-forget code then it doesn't matter. However, if
you make code which potentially needs to be enhanced/fixed in the future
(and specially by someone else than you), then clarity is a big plus.
> A good programmer can deal with code that's hard
> to read
Yes, after cursing you and your family for making it so hard to read.
--
#macro M(A,N,D,L)plane{-z,-9pigment{mandel L*9translate N color_map{[0rgb x]
[1rgb 9]}scale<D,D*3D>*1e3}rotate y*A*8}#end M(-3<1.206434.28623>70,7)M(
-1<.7438.1795>1,20)M(1<.77595.13699>30,20)M(3<.75923.07145>80,99)// - Warp -
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Tek <tek### [at] evilsuperbrain com> wrote:
> We like the clunkier syntax *because* it is harder to use and requires more
> thought from the programmer. In our situation this is a good thing.
Good luck trying to maintain and enhance such code in the future then.
--
#macro N(D)#if(D>99)cylinder{M()#local D=div(D,104);M().5,2pigment{rgb M()}}
N(D)#end#end#macro M()<mod(D,13)-6mod(div(D,13)8)-3,10>#end blob{
N(11117333955)N(4254934330)N(3900569407)N(7382340)N(3358)N(970)}// - Warp -
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
In article <4038bb04@news.povray.org> , Warp <war### [at] tag povray org> wrote:
> Good luck trying to maintain and enhance such code in the future then.
If you write games, you don't have to, I suppose. All you need is a few
patches later on when bad coding style produced plenty of bugs in the
initial release version ;-)
Thorsten
____________________________________________________
Thorsten Froehlich, Duisburg, Germany
e-mail: tho### [at] trf de
Visit POV-Ray on the web: http://mac.povray.org
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
"Warp" <war### [at] tag povray org> wrote in message
news:4037f302@news.povray.org...
> Patrick Elliott <sha### [at] hotmail com> wrote:
> > But it can happen.
>
> Of course it can happen. And it can also happen that a function
> named "multiply" calculates the square root. But that doesn't mean
> it's not avoidable. It just means the design of the program/library
> has a flaw.
Holy cow, this thread grew a lot. I was in bed all Saturday (not sick, just
very, very tired) and missed out on the fun. I have too much to do to catch
up.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
In article <4038a02f@news.povray.org>, Warp <war### [at] tag povray org>
wrote:
> Christopher James Huff <cja### [at] earthlink net> wrote:
> > Pass everything by reference
>
> That can be problematic.
...snip...
> Int foo = container.size(); // <- gets a *reference*
No, that initializes an Int named foo to the object returned by
container.size. Not a problem.
This was a problem in Sapphire...not a major one, but it required
annoying additional code to create a copy. Now I have an additional
syntax for creating variables:
def foo: val; //defines a variable foo attached to the value val
def foo = val; //defines a variable foo attached to a copy of val
> The big problem is that since your variable is actually a reference
> to the original 'numberOfItems' variable, you'll end up breaking the
> container.
You could also introduce const references...not sure if its worth the
trouble.
> I don't know enough about Java to know how this problem is avoided
> there.
Java passes everything by value. Objects are only handled through
references, those references are passed by value. And it will break in
the way you describe above, but it isn't very common...in this case, you
would use the primitive int type instead of an integer object.
--
Christopher James Huff <cja### [at] earthlink net>
http://home.earthlink.net/~cjameshuff/
POV-Ray TAG: <chr### [at] tag povray org>
http://tag.povray.org/
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
In article <403897c7$1@news.povray.org>, "Tek" <tek### [at] evilsuperbrain com>
wrote:
> Couldn't compilers inline functions 10 years ago?
Not as intelligently.
> Anyway, my point isn't just the function call overhead, it's the fact
> that it's not an operator internally supported by the compiler with a
> bunch of rules, it's a series of instructions of unspecified length
> elsewhere.
Which you have to call no matter what. It being done through an operator
function rather than through an explicit member function call makes
exactly zero difference.
> Well, it can lose the function call overhead, but not the overhead of
> it being a function (i.e. several instructions) rather than a simple
> instruction (which is really my point).
Zero overhead. None. Nada. Not one extra instruction.
> What I'm saying is I want "+" to produce the same amount of assembler code
> whenever I use it.
Well, you can't. Adding some things takes more work. Using member
functions doesn't help this at all.
> > For example, suppose you have this (in C++):
>
> Aha! but you'd never define an object for a type inherently supported by the
> compiler, only for types which require something more complex.
Actually, iterators often do exactly this, being a thin wrapper over a
pointer.
> So you end up with "+" becoming different amounts of compiled code
> depending on the context in which it's used. This makes it harder to
> optimise code, since it is harder to keep track of where the more
> complex + functions are being invoked.
Just be aware of what you're adding. It's no harder than keeping track
of a bunch of methods named add(), mult(), etc, and the code is much
easier to read.
> I think you've missed my point, I'm not saying operator overloading does
> anything different to function calls, I'm saying addition functions for two
> matrices are different to addition functions for the processor's inbuilt
> types, and it is useful when optimising to keep track of this difference.
How is this so? If you need to add two matrices, you need to add two
matrices. You can't do this with the same code for adding two integers.
> Operator overloading is great if you want to code at a higher level without
> being bogged down by thinking about what's happening at the lowest level, but
> when optimising code you want to do the opposite! Heck, if were even remotely
> feasible we'd write everything in assembler...
No...then you run into the "can't see the forest for the trees" problem.
You'll spend too much time optimizing tiny little things, and completely
miss larger optimizations that can have a huge impact. And I still
haven't seen an argument against including operator overloading in a
language...even if this were true, it would apply only to specific
projects.
--
Christopher James Huff <cja### [at] earthlink net>
http://home.earthlink.net/~cjameshuff/
POV-Ray TAG: <chr### [at] tag povray org>
http://tag.povray.org/
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |