POV-Ray : Newsgroups : povray.advanced-users : Object Oriented POV code Server Time
29 Jul 2024 18:25:49 EDT (-0400)
  Object Oriented POV code (Message 80 to 89 of 179)  
<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>
From: Andreas Kaiser
Subject: Re: Object Oriented POV code
Date: 22 Feb 2004 00:10:11
Message: <n8ag309hemfhpmj8jnt5j5s3k8gr66rm62@4ax.com>
On Sat, 21 Feb 2004 22:26:59 -0500, Christopher James Huff
<cja### [at] earthlinknet> wrote:

>In article <403814c4$1@news.povray.org>, "Tek" <tek### [at] evilsuperbraincom> 
>wrote:
>
>> Well, I know a good argument against it. So good in fact that it's the reason
>> why every games programmer I know doesn't use operator overloading: It hides
>> processing.

This might be a 'learning' problem if you aren't aware of the
operators 'hidden' complexity. 

>So do functions.

Yes, same problem here. There's no correlation between length of
function name and complexity. 
If you call a Trace() function you should know why.
May be to write a trace record to a log file, may be to start a render
that will be finished some months later.

>[...]

>> Of course, for less speed critical stuff like describing POV scenes, I'd
>> wholeheartedly support it. But I'm just saying there *is* a good argument
>> against it.

May be, but it isn't speed.
For example, I have rewritten POV-Ray's core using VECTOR, COLOUR and
some other classes (with appropriate operators).
It was as fast as the original version but shorter and IMHO much more
readable.
The macros required to do trivial colour/vector arithmetic are
'information hiding' in the worst sense. They blow up source code and
add visual noise which makes it sometimes almost impossible to see
what's going on.
OK, I'll stop now ;-)

>I still haven't heard one yet.


-- 
Andreas


Post a reply to this message

From: Tek
Subject: Re: Object Oriented POV code
Date: 22 Feb 2004 04:11:47
Message: <40387253$1@news.povray.org>
> >> Well, I know a good argument against it. So good in fact that it's the
reason
> >> why every games programmer I know doesn't use operator overloading: It
hides
> >> processing.
>
> This might be a 'learning' problem if you aren't aware of the
> operators 'hidden' complexity.

My point is that a+b takes a different length of time according to the types of
a and b, where as MyMatrixAddFunction(a,b) takes the same length of time always,
plus you can search for it to see where it's executed in the code, plus you can
stick a nice big comment on the prototype of it saying "//avoid calling this
unless really necessary, it's very slow" so that anyone who doesn't know how to
add these two things has to look up the function prototype and read the comment
and reconsider the code they're writing.

I'm not trying to suggest the source looks nicer with more function calls, it
certainly doesn't. I'd even say I like operator overloading a lot, it's
extremely useful in high-level programming applications. I'm merely saying that,
in practice, it makes it easier to write code that is much more complex to
execute than it is to read or write. This is both it's strongest and weakest
point.

> The macros required to do trivial colour/vector arithmetic are
> 'information hiding' in the worst sense. They blow up source code and
> add visual noise which makes it sometimes almost impossible to see
> what's going on.

As I said, I support using + for vectors since that's what it will compile to.
Although I don't really see your point about visual noise, function calls
certainly make it harder to write clearly readable code but since it's harder
all it takes is more effort. Programming isn't about making things easier for
the programmer, it's about making the end result better. In application software
or high level programming these two ideas are very compatible, but in time
critical stuff like game engines people like me have to give ourselves headaches
trying to optimize out one cycle in a render loop in order to improve the
performance of the game. Operator overloading hinders us in this quest.

Damn that made me sound so cool...

-- 
Tek
www.evilsuperbrain.com


Post a reply to this message

From: Warp
Subject: Re: Object Oriented POV code
Date: 22 Feb 2004 05:49:40
Message: <40388944@news.povray.org>
Christopher James Huff <cja### [at] earthlinknet> wrote:
> I am. I definitely would want operator overloading. I've never seen a 
> good argument against it...

  Ask Java worshippers. They know. ;)

  I personally am all for operator overloading in the same way as you,
and it's one thing why I hate Java so much.

> > but interfaces are obsolete.
> > If you want to make an "interface", just make an abstract class.

> Interfaces are not obsolete. As for abstract classes...what are you 
> talking about?

  Interfaces are obsolete of you can make abstract classes. And why
wouldn't you (unless you want to make the language so that it does
not support virtual functions, which would limit its OO capabilities
by a whole lot).

  A class is abstract if it has pure virtual functions (that is,
the class does not implement the virtual function(s) and thus cannot
be instantiated because of this; it can only be used through
inheritance so that the derived class implements the virtual
function(s) in question).
  If every member function it has is purely virtual, then it's basically
the same thing as an interface. (This is how "interfaces" are done in C++
if you *really* need to make one.)

> >   They are necessary, believe me... ;)

> Sorry, but I don't. I've never accidentally tried to access a private 
> member.

  That's right. *You*. But that's ok only for as long as you don't
distribute that library of yours containing public member variables...
Someone will inevitably use it in the wrong way and his code can then
break with an updated version of the library.

> They do serve a documentation purpose

  That's not their purpose at all. Public and private parts have clear
maintainability, abstraction and safety purposes.
  If you can't use the library in the wrong way (ie. the compiler does
not allow you to), then you will not use it in the wrong way.

> but IMO if a language has 
> them, they should be defined in a separate place, with only the public 
> interface in a header file.

  Well, that's just a question of implementation of the interpreter/compiler.
If you can implement the interpreter so that the private part does not need
to be specified at the same place as the public part, good thing. (In C++
this is not possible for technical reasons, but in an interpreted
scripting language it may very well be possible.)

> But for POV, this would be too restrictive 
> and complex, IMO.

  What do you mean "restrictive"?
  That's like saying #local is too restrictive. It doesn't make sense.

  The private part of a class has the same visibility purpose as for
example #local has: It's safer to use #local whenever possible than
always using #declare.

> >   I would even go so far that member variables are always private (ie.
> > you *can't* make them public).

> I wouldn't care for this. Think of vector member access...vec.x, vec.y, 
> etc...vec.x() just adds more visual noise.

  If you read my article completely I suggested adding support for calling
member functions without parentheses (supposing they don't take parameters).
There's nothing problematic with that.

-- 
#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

From: Warp
Subject: Re: Object Oriented POV code
Date: 22 Feb 2004 06:07:31
Message: <40388d73@news.povray.org>
Tek <tek### [at] evilsuperbraincom> wrote:
> i.e. when you compile a+b, you expect it to compile to a simple add instruction,
> and these days most processors can do vector maths so I'd certainly support it
> being used for them. The problem is if you've defined your own type of data that
> has a "+" function, you incur the cost of a function call invisibly in your
> code. This is a very bad thing for time-critical applications like computer
> games. Things like this make optimising an absolute nightmare.

  This may have been true 10 years ago.

  Current compilers can usually optimize the overhead (eg. the function
call) away completely (supposing the operator function is inline).
If you make a class which uses operator overloading for simple tasks
(such as adding two internal values together) you should definitely
make them inline, after which the compiler will be able to optimize
all the overhead away.

  For example, suppose you have this (in C++):

class MyInt
{
    int value;

 public:
    MyInt(int init=0): value(init) {}

    int operator+(const MyInt& rhs) const { return value+rhs.value; }
};

  Now if you do something like this:

MyInt a=1, b=2, c;
c = a+b;

I would be very surprised if the code generated by a modern compiler
would be any different from the code which it would generate if you
replace the MyInt class with:

typedef int MyInt;


  PS. In fact, I just tested this with gcc. I added the following
method to the MyInt class for easier usage:

    operator int() { return value; }

and then made a code like this:

int foo()
{   
    MyInt a=1, b=2, c;
    c = a+b;
    return c;
}

  Using the MyInt class or typedeffing MyInt to int resulted in identical
assembler code (when using optimizations):

.LLFB3:
        !#PROLOGUE# 0
        !#PROLOGUE# 1
        retl
        mov     3, %o0

  This is sparc asm, and if we "translate" it back to C++ it means
the same thing as:

int foo()
{
    return 3;
}

  So using a class with operator overloading did not ask any overhead
*at all* to the code.

-- 
plane{-x+y,-1pigment{bozo color_map{[0rgb x][1rgb x+y]}turbulence 1}}
sphere{0,2pigment{rgbt 1}interior{media{emission 1density{spherical
density_map{[0rgb 0][.5rgb<1,.5>][1rgb 1]}turbulence.9}}}scale
<1,1,3>hollow}text{ttf"timrom""Warp".1,0translate<-1,-.1,2>}//  - Warp -


Post a reply to this message

From: Tek
Subject: Re: Object Oriented POV code
Date: 22 Feb 2004 06:51:35
Message: <403897c7$1@news.povray.org>
>   This may have been true 10 years ago.

But I wasn't programming games 10 years ago.

>   Current compilers can usually optimize the overhead (eg. the function
> call) away completely (supposing the operator function is inline).

Couldn't compilers inline functions 10 years ago?

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.

> If you make a class which uses operator overloading for simple tasks
> (such as adding two internal values together) you should definitely
> make them inline, after which the compiler will be able to optimize
> all the overhead away.

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).

What I'm saying is I want "+" to produce the same amount of assembler code
whenever I use it.

>   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. 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.

Plus when someone is writing the code if they have to call
PerformReallySlowAndComplicatedAddition( a, b ) rather than a+b it tends to make
people more aware of what they're doing. It doesn't completely solve the problem
of writing optimised code, I'm just saying it makes it easier to keep track of
what's actually going on at the lowest level.

>   So using a class with operator overloading did not ask any overhead
> *at all* to the code.

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.

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...

-- 
Tek
www.evilsuperbrain.com


Post a reply to this message

From: Andrew C on Mozilla
Subject: Re: Object Oriented POV code
Date: 22 Feb 2004 07:13:48
Message: <40389cfc@news.povray.org>
>>I wouldn't care for this. Think of vector member access...vec.x, vec.y, 
>>etc...vec.x() just adds more visual noise.
> 
>   If you read my article completely I suggested adding support for calling
> member functions without parentheses (supposing they don't take parameters).
> There's nothing problematic with that.

Eiffel does this...

(Can be slightly confusing at times... but then, so can most things!)

Not sure what you do about vec.x := 7... (But then, for certain objects 
it might be that you can't change one attribute without changing another 
as well... can't think of a good example right now...)


Post a reply to this message

From: Warp
Subject: Re: Object Oriented POV code
Date: 22 Feb 2004 07:15:07
Message: <40389d4b@news.povray.org>
Tek <tek### [at] evilsuperbraincom> wrote:
> 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).

  The only alternative to operator overloading is to use a member function.
So how is that any different?

> >   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. 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.

  You missed my point completely.

  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.
  If you want to make, for example, a rational number type (which contains
two integers), then it doesn't matter if you use it with operators or with
regular member function calls: Using operators is not any slower.

> Plus when someone is writing the code if they have to call
> PerformReallySlowAndComplicatedAddition( a, b ) rather than a+b it tends to make
> people more aware of what they're doing.

  So you are saying that even if the addition would be extremely fast you
still should not use operator overloading? Why?

  Using operators makes the code cleaner and easier to read with complex
expressions.
  (This is IMHO a true problem in Java. You can't make in Java things like
"a = b + c*(d*c-e);" with your own defined type.)

> 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...

  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.

-- 
#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

From: Andrew C on Mozilla
Subject: Re: Object Oriented POV code
Date: 22 Feb 2004 07:15:26
Message: <40389d5e$1@news.povray.org>
> IMHO this comes down to 'pov ain't oo' - I don't think anyone denies 
> that oo capabilities in pov wouldn't be at the very least interesting, 
> but that's not the issue....

POV sure ain't OO. No doubt about it ;-)

(...unless you start getting into an argument about what OO "is"... *sigh*)

Question: what IS the issue? (Maybe I'm just slow...)

Andrew @ home on Mozilla.


Post a reply to this message

From: Thorsten Froehlich
Subject: Re: Object Oriented POV code
Date: 22 Feb 2004 07:21:57
Message: <40389ee5$1@news.povray.org>
In article <403897c7$1@news.povray.org> , "Tek" <tek### [at] evilsuperbraincom> 
wrote:

> Couldn't compilers inline functions 10 years ago?

Not as well, no.

> 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.

> 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.

    Thorsten

____________________________________________________
Thorsten Froehlich, Duisburg, Germany
e-mail: tho### [at] trfde

Visit POV-Ray on the web: http://mac.povray.org


Post a reply to this message

From: Warp
Subject: Re: Object Oriented POV code
Date: 22 Feb 2004 07:27:27
Message: <4038a02f@news.povray.org>
Christopher James Huff <cja### [at] earthlinknet> wrote:
> Pass everything by reference

  That can be problematic.

  Suppose you have something like this:

class ItemContainer
{
 private:
    Int numberOfItems;

 public:
    ...
    Int size() { return numberOfItems; } // <- returns a reference
    ...
};
...


ItemContainer container;
// add things to 'container'

Int foo = container.size(); // <- gets a *reference*
foo -= 100; // Ooops! The container breaks badly!

  The thing is that in principle the code is not doing anything malign
on purpose. It's only natural that you take eg. the size of the container
to a variable and then use this variable for example as a loop counter
(eg. to go through all the items in the container).
  The big problem is that since your variable is actually a reference
to the original 'numberOfItems' variable, you'll end up breaking the
container.

  I don't know enough about Java to know how this problem is avoided
there.

-- 
#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

<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.