Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Check if integer is bigger OR smaller

Tadao Nordenskiold
Registered User
Join date: 9 May 2009
Posts: 37
12-26-2009 16:07
I'm not really sure how to do this, but I need an if-statement that can check wether an integer is larger than -3 but less or equal to 7.

Can anyone tell me how to do this please?

Best regards,
/Tadao
Nyx Alsop
Registered User
Join date: 14 Dec 2008
Posts: 252
12-26-2009 16:15
if(integer > -3 && integer <= 7){

}
Tadao Nordenskiold
Registered User
Join date: 9 May 2009
Posts: 37
12-26-2009 16:21
Ah.. &&.. thanks.. :)
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-27-2009 00:51
lsl has no *short circuiting, so even if the first test is false making the second text impossible (because both need to be true) you'll still do the work of the second test. the only way to get around this in lsl is to do the tests separately, one inside the other like...

CODE

if (num > -3){ //-- if false we get to exit early, yay
if (num <=7){ //--only gets tested if the first one was true
//-- yay both are true
}
}


kinda counter-intuitive I know, but it you place the most likely to be false test first, you'll do less work in the program on average.

*this is the ability of a language to skip tests if it's known that further tests won't change the result. for && tests that means skipping the second if the firs is false, for || tests that means skipping the second if the first is true.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Tadao Nordenskiold
Registered User
Join date: 9 May 2009
Posts: 37
12-27-2009 06:25
Hmm.. so if I get this right Void, it should not work as I want with && as described by Nyx?

Because I tried it, and it did work.
Atleast with my tests..

The thing that I am trying to do is the following:

I'm retreiving some information from my MySQL database, and gets (in this case) this information:
05c9fe42-8d89-401d-a9a5-2d82af58e16f|14224|03-Mar-2010|65
(My) UUID | Port | Expiredate |Daysleft

Then I pick out the "Days left" part and do the tests.
if (Daysleft > -7 && Daysleft <= 7)
(changed from -3 to -7)
{
(if Dayeleft < 0)
{
Daysago = llDeleteSubString((string)Daysleft,0,0);
message = "Your expiration date was " +Dagsago +";(" +Expiredate +";). You have to renew in order to continue using the service."
(sent as llDialog to UUID)
}
else
{
message = "Your service will be suspended and stop working in " +Daysleft +" days unless you renew within the next " +Daysleft +" days. Your expire date is: " +Expiredate +"."
(sent as llDialog to UUID)
}
else if (daysleft > 7)
{
message = "You have more than 7 days left of your service. You can renew when ever you want, but it is not nessecary at this point. You currently have " +Daysleft +" days left of your service."
(sent as llDialog to UUID)
}
}

(Just examples of what I am doing, typecasting and typos may or may not exist in the example above).

And this seems to work pretty good so far.
Is there a reason to why this works for me despite what you said Void, or is there something else I havn't thought of?
Orcourse I have tried with different results of the reply from my sql replies.
Both with negative and positive Daysleft results.
Dora Gustafson
Registered User
Join date: 13 Mar 2007
Posts: 779
12-27-2009 06:47
From: Nyx Alsop
if(integer > -3 && integer <= 7){}
This approach is perfectly valid.
There is absolutely no reason to bother if the simulator makes both tests.
It is true that if the first test(int>-3) fail the outcome of the combined test(int>-3 && int<=7) is known before the second test(int<=7) is made.
How many pico Seconds do you think it will take for a modern computer to to retrieve and compare two integers?
I can think of one case only where it would matter: in a short loop repeated millions of times:)
_____________________
From Studio Dora
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-27-2009 09:01
a couple of integers, not likely to matter much, especial by itself.
other comparisons the impact can be greater.

lsl being what it is though it's good to know, and if the thousands of scripts that run on a sim all do things more efficiently it benefits everyone.

ETA:
sorry if I was unclear, both work just fine.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Pale Spectre
Registered User
Join date: 2 Sep 2005
Posts: 586
12-27-2009 09:06
Efficiency aside, the Short Circuit can still be important. This example is a contrivance but illustrates the problem:

CODE

default
{
touch_start(integer total_number)
{
float x = 0;
if (x > 0 && 2 / x == 1) llOwnerSay("True");
else llOwnerSay("False");
}
}


As it stands this script will fail with a Math Error (divide by zero) because the x > 0 test doesn't prevent the 2 / x test from being executed.
_____________________
Dora Gustafson
Registered User
Join date: 13 Mar 2007
Posts: 779
12-27-2009 12:52
From: Pale Spectre

CODE

default
{
touch_start(integer total_number)
{
float x = 0;
if (x > 0 && 2 / x == 1) llOwnerSay("True");
else llOwnerSay("False");
}
}

As it stands this script will fail with a Math Error (divide by zero) because the x > 0 test doesn't prevent the 2 / x test from being executed.

LOL that is true:) but still the code should be run in the programmers head before letting a machine do it and the programmer should know the language at hand.
_____________________
From Studio Dora
Sindy Tsure
Will script for shoes
Join date: 18 Sep 2006
Posts: 4,103
12-27-2009 13:46
The no-shortcutting stuff isn't something I worry about to save a few computrons - it's when you're testing the result of functions that have side effects that you have to be careful.

Plus what Pale says.. :)
_____________________
Sick of sims locking up every time somebody TPs in? Vote for SVC-3895!!!
- Go here: https://jira.secondlife.com/browse/SVC-3895
- If you see "if you were logged in.." on the left, click it and log in
- Click the "Vote for it" link on the left
Jesse Barnett
500,000 scoville units
Join date: 21 May 2006
Posts: 4,160
12-27-2009 15:41
Kind of redundant now but just wanted to show the example I learned a couple of years ago in how not short cutting can be bad in a script. I do still use && depending on the circumstances thou.

CODE

default {
touch_start(integer count) {
integer a = 3;
if ( a < 2 && ++a > 4){};
llOwnerSay((string)a);
}
}

That will return 3 in LSLEditor which does shortcut but will return 4 in SL where it is not.
_____________________
I (who is a she not a he) reserve the right to exercise selective comprehension of the OP's question at anytime.
From: someone
I am still around, just no longer here. See you across the aisle. Hope LL burns in hell for archiving this forum
Anya Ristow
Vengeance Studio
Join date: 21 Sep 2006
Posts: 1,243
12-27-2009 17:15
From: Tadao Nordenskiold
Is there a reason to why this works for me despite...


You have been given info that is advanced enough that you have no hope of remembering it when the time comes that it'll be helpful.

If you ask a coder how to drink water from a glass you will be given all kinds of probably true but not very helpful info, and you'll just go thirsty wondering about it.

Just drink :)
_____________________
The Vengeance Studio Gadget Store is closed!

Talarus Luan
Ancient Archaean Dragon
Join date: 18 Mar 2006
Posts: 4,831
12-27-2009 21:07
I follow a pretty simple set of guidelines when it comes to conditionals:

1. Use boolean operators if each conditional operand is independent of all others. If there are dependencies, use nesting. ONLY use short-circuiting when and where you know it exists, or have compiler pragmas which you can control.
2. Avoid modification operations (assignments, pre/post-increment/decrement) in conditionals. Yes, you can do it, but because one *can* do a thing doesn't mean that one *should* do a thing. You wouldn't believe the sheer number of bugs that could be avoided by simply avoiding this "feature" of C-like languages.
3. Avoid "auto-tests" (using the notion that integer expression results just "happen" to be zero or nonzero as true/false); always build conditional expressions as strings of boolean operators and operands.
4. Another one which I always use that saves me a lot of headaches: ALWAYS explicitly parenthesize infix expressions. Operator precedence rules are about as consistent as the weather, and it is annoying to track down bugs related to them when debugging.

Yeah, it means my code isn't 100% efficient, and I have to type more, but I spend WAY less time debugging and patching later. Frankly, the kinds of optimizations I am avoiding in my code should be taken care of by the compiler (and have been in REAL compilers), and the savings aren't really all that significant, compared to the gross inefficiencies embodied in SL in general.
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-28-2009 00:51
From: Talarus Luan
4. Another one which I always use that saves me a lot of headaches: ALWAYS explicitly parenthesize infix expressions. Operator precedence rules are about as consistent as the weather, and it is annoying to track down bugs related to them when debugging.


I'd have to disagree about the other three, I think they are very useful to learn, and won't cause you headaches IF you learn how they work (and not just cut and paste them), but this one I can't agree enough with especially in LSL. I'd add that it's also a good habit to parenthesize any assignments within a larger code string, whether it's a function return, or a test.

From: someone
Frankly, the kinds of optimizations I am avoiding in my code should be taken care of by the compiler (and have been in REAL compilers)

funny, because that's exactly why I offer them up; because LSL doesn't do them.

styles differ though, and I won't argue that it's better to learn the basics well, before including any optimizations. we do have scripters of varying levels that read so I try to offer them up as a "next step" for anyone ready to advance their understanding.

oo I think I have a new bit to add to my sig.... "don't try this at home"
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-28-2009 02:13
I guess I should mention some cases where you aren't going to want to use the manual shortcutting I showed above....

when your if test is followed by and else, it means the else won't fire if the first half is true, unless you use a second else clause, which would usually remove any gains.

when using a while loop, because the while test would have to drop at least partially inside the loop and then jump out, which is likely to be LESS efficient.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Talarus Luan
Ancient Archaean Dragon
Join date: 18 Mar 2006
Posts: 4,831
12-28-2009 08:32
From: Void Singer
I'd have to disagree about the other three, I think they are very useful to learn, and won't cause you headaches IF you learn how they work (and not just cut and paste them),


From experience, the only use I can see to learn them is to learn why not using them is a good thing. Yes, they will still cause you headaches even if you learn how they work. I know how they work just fine and used them for many years. After many years of debugging headaches caused by these very practices, I decided that it was time to go back to not using them and voila! I started saving myself a significant amount of time not only in coding, but also in maintaining said code. The people who have had to come back later and maintain my code also have mentioned appreciation for the decisions I made as well, rather than complaining about the headaches of deciphering the code I wrote before I made them.

From: someone
funny, because that's exactly why I offer them up; because LSL doesn't do them.


It doesn't matter. Unless you're doing something that NEEDS optimization for speed, the savings aren't worth the hassle. I don't subscribe to the notion that ALL code needs to be optimized ALL the time. If I did, I would write everything in Assembler (in SL's case, an LSO Assembler) and be done with it. The whole point in using a high-level language is for ease of development/maintenance; the "human-readable" aspect.

From: someone
styles differ though, and I won't argue that it's better to learn the basics well, before including any optimizations. we do have scripters of varying levels that read so I try to offer them up as a "next step" for anyone ready to advance their understanding.


It's not simply a matter of "style"; the methodology has a practical application, learned after years of dealing with both "methods", both in terms of writing code, and maintaining code that other people have written, as well as porting code. Yes, code portability is still an important aspect, even with LSL. As virtual worlds continue to proliferate, taking algorithms and functions written for one and porting them to another may become prevalent.
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-28-2009 09:33
I've never experienced any more or less difficulty debugging, because of any of those practices, nor any noticeable difference in time spent debugging. maybe I'm lucky, maybe it has to do with how I go about it; I couldn't say for certain what the difference is.

as for portability, I think porting anything from lsl is actually going to be inherently easier, simply because of all the things lsl doesn't support natively. there are vanishingly few optimizations in lsl that aren't supported in other languages, or aren't simply another option on the same functional level. TBH I can't think of one offhand that apply.

now I'll agree some coding practices will be frowned upon in a shared environment where others are maintaining code you've written, but that's not generally the rule with coders in lsl.

and lastly, given the severe limitations of size and speed present in lsl, coupled with the limited nature of VM, the faster and more memory efficiently the code is written to run, the better that code will run in that environment by comparison, as well as freeing up more space and speed for the next bit of code, ultimately allowing smoother operation of the sim, or more likely the ability to pack it with more features before the limits are hit.

it's simple math; if there's only so many frames to go around, the things that use the least are going to still be working the smoothest, because they get by on less. and when you only have X space to go around, that will almost assuredly be filled, you get to have more working options if those things are tightly coded.

does that mean that the code will be less "readable". perhaps for some, which is why I can't encourage people strongly enough to learn them, AND why they work. and to comment things are are non obvious, or non-standard. once you get there, you'll always know what the code is doing, and probably WHY too.

(and seriously? all this over short circuiting? :: boggle :: )
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Rolig Loon
Not as dumb as I look
Join date: 22 Mar 2007
Posts: 2,482
12-28-2009 11:01
From: Void Singer
we do have scripters of varying levels that read so I try to offer them up as a "next step" for anyone ready to advance their understanding.

Of all the rationales you offer, this one resonates best with me, Void. Despite having worked in a range of programming languages beginning with Fortran II in the early 1960s, I am not a professional scripter. More than that, I'm a LSL neophyte. My approach to scripting tends to be brute force, definitely not optimal for either speed or efficient memory use. I appreciate the fact that your coding is stylistically consistent and compact. Your good examples make me think carefully beyond syntax about better ways to express the logic of a problem, for both efficiency and readability. Many of the technical nuances will probably always be over my head, but for purely pragmatic reasons I like your "next step" attitude.
_____________________
It's hard to tell gender from names around here but if you care, Rolig = she. And I exist only in SL, so don't ask.... ;)

Look for my work in XStreetSL at
Talarus Luan
Ancient Archaean Dragon
Join date: 18 Mar 2006
Posts: 4,831
12-28-2009 11:31
From: Void Singer
I've never experienced any more or less difficulty debugging, because of any of those practices, nor any noticeable difference in time spent debugging. maybe I'm lucky, maybe it has to do with how I go about it; I couldn't say for certain what the difference is.


Have you spent a lot of time using both practices to compare, or just one? If the latter, then your observations don't surprise me.

From: someone
as for portability, I think porting anything from lsl is actually going to be inherently easier, simply because of all the things lsl doesn't support natively. there are vanishingly few optimizations in lsl that aren't supported in other languages, or aren't simply another option on the same functional level. TBH I can't think of one offhand that apply.


Pascal, for example, doesn't permit assignments in conditionals, and expects all conditional expressions resolved to booleans. As such, those "optimizations" are not portable.

From: someone
now I'll agree some coding practices will be frowned upon in a shared environment where others are maintaining code you've written, but that's not generally the rule with coders in lsl.


It happens a lot more often than you might realize. Especially people who publish scripts addressing a particular problem. If I don't write my own, I end up rewriting those scripts before I use them to conform better to these practices. It is time I would rather not have to spend, but it is either that or more annoyance/hassle when I have to debug/fix/migrate/port/maintain that code in the future, especially when people are yelling in my ear about it being broken. <.<

From: someone
and lastly, given the severe limitations of size and speed present in lsl, coupled with the limited nature of VM, the faster and more memory efficiently the code is written to run, the better that code will run in that environment by comparison, as well as freeing up more space and speed for the next bit of code, ultimately allowing smoother operation of the sim, or more likely the ability to pack it with more features before the limits are hit.

it's simple math; if there's only so many frames to go around, the things that use the least are going to still be working the smoothest, because they get by on less. and when you only have X space to go around, that will almost assuredly be filled, you get to have more working options if those things are tightly coded.


That's the problem. The math doesn't support the notion, except in very specific cases.

As for speed, the gains of eliminating one cycle in a billion are nothing compared to the savings in readability alone.

As for space, when you are dealing with frame sizes of 4k (the standard VM page size), a few bytes isn't going to significantly impact memory usage. Assuming a savings of 16 bytes per 4k, that's less than half a percent savings over all scripts in any particular simulator. Big deal. <1.2MB per 300MB, based on the proposed script limits.

This doesn't even touch on the fact that, in some cases, using these practices has no impact on speed/space, and can actually be faster/smaller, depending on the language/compiler used.

I think the savings in hassle and readability are worth it.

From: someone
does that mean that the code will be less "readable". perhaps for some, which is why I can't encourage people strongly enough to learn them, AND why they work. and to comment things are are non obvious, or non-standard. once you get there, you'll always know what the code is doing, and probably WHY too.


Oh, I most definitely encourage people to learn them AS WELL AS when/where/why they should/shouldn't be used.

If you've never gone back to code you've written in the past and had to puzzle out what the heck you were doing, then you must be a God of Programming. That, or a relative newbie. ;)

From: someone
(and seriously? all this over short circuiting? :: boggle :: )


Seriously, the issue is about more than "short circuiting". Please stop attempting to minimalize it, k?
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-28-2009 23:40
I've worked in environments were both were the norm, so be surprised. the only problems I've had with old code of mine is when I wrote crypt-i-code wtih nondescript variables and no comments... I don't do THAT any more.

I just visited a sim that was only occupied by a few av's, 3k running script... multiply that by you're meager estimate of 16 bytes and tell me what the savings on that sim are? and who those scripts belonged to and which scripts ran without noticeable lag longer... I've seen busy sims with nearly 5 times that.

and it's not minimizing to say all this sprang from including an example of how to shortcut in lsl, it's just a wonderment that THIS conversation sprang from that one.

PS
if you're porting LSL to pascal, I've gotta wonder why. and is it really so hard to move an assignment up from the test? you obviously know it's not acceptable syntax in that language, just as I'm sure you know that other languages support not only assignment, but declaration in their test, at the very least in "for" loops. coincidental integer test for zero = false are also pretty easy to redefine in the integer sense rather than doggedly trying to fit them to the local syntax of TRUE/FALSE, and possibly more useful.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Talarus Luan
Ancient Archaean Dragon
Join date: 18 Mar 2006
Posts: 4,831
12-29-2009 12:16
From: Void Singer
I've worked in environments were both were the norm, so be surprised. the only problems I've had with old code of mine is when I wrote crypt-i-code wtih nondescript variables and no comments... I don't do THAT any more.


Well, I guess you're just a better programmer than I am (and many others are), so just ignore what I am saying as hogwash, then. :)

From: someone
I just visited a sim that was only occupied by a few av's, 3k running script... multiply that by you're meager estimate of 16 bytes and tell me what the savings on that sim are? and who those scripts belonged to and which scripts ran without noticeable lag longer... I've seen busy sims with nearly 5 times that.


Well, let's do the math..

Most scripts in circulation probably average out in the lower end of the Mono memory size, either because they are still on the old LSL VM, or are simple scripts that do not use a lot of memory, so let's be conservative and say that 16k is the average size. It is probably lower, but like I said, let's be conservative here.

Given the example of 16 bytes savings per 4k, that would be 64 bytes savings per script, times 3000, would be a whopping 192k. OK, then let's say it is 5 times that. That amounts to just under the huge size of ONE megabyte. Wow. That's a lot!

Not really.

Then again, for the ACTUAL memory allocation, there is the problem of waste in allocation. I won't presume that memory allocation for code is going to back-fill unused space in 4k pages, especially since there are already indications from LL that it does not. So, on average, there would be 2048 bytes of memory waste PER SCRIPT. For 3,000 scripts, that's ~6MB, and ~30MB for the "5 times" example.

The real point is that, for the most part, the "waste" in the script methodologies literally disappears in the "noise" of actual waste in the system we have no control over. In other words, most times, the "extra" bytes we're talking about fill space that would otherwise have been wasted as it was, thus no effective EXTRA "waste" is observed.

From: someone
and it's not minimizing to say all this sprang from including an example of how to shortcut in lsl, it's just a wonderment that THIS conversation sprang from that one.


It is when that's not the reason I posted it in the first place. The discussion had already turned to a more generic discussion on conditions, compared to the specific question the OP had, which had nothing to do with short-circuiting in the first place. You extended the discussion more generally into short-circuiting, then I extended it more generally into a "better practices" recipe list for conditionals in general.

From: someone
PS
if you're porting LSL to pascal, I've gotta wonder why. and is it really so hard to move an assignment up from the test? you obviously know it's not acceptable syntax in that language, just as I'm sure you know that other languages support not only assignment, but declaration in their test, at the very least in "for" loops.


For the most part, it was just an example, since you said you couldn't think of one, I provided one of which I am aware. I also happen to be working on a VW development project which is using something similar to Pascript as one of its primary scripting languages.

It illustrates the point of non-portability. Sure, other languages allow it; sure, some allow declarations anywhere, but they ALSO allow them to NOT be put in conditionals and loop control statements as well, so you're not losing anything of significance by NOT putting them there, and gaining in terms of readability. I can't count the times I have gone to debug some code someone wrote (not in LSL, but in other scripting and regular languages) where someone put a declaration somewhere in the middle of a sea of code, and I needed to know the specifics of its declaration in order to continue debugging. I don't imagine that the original programmer would have had any easier a time if he/she came back to the code after a year and was doing the debugging. "Where did I put that stupid declaration???" Seen it happen.

Most structures languages (even LSL) allow you to put all your code on one long line, too. That doesn't mean it is a good, practical method for you to do so.

Onwards to a specific example...

There is no code/speed/efficiency advantage to using this kind of construct:

if ((fTheta=llAngleBetween(llGetRot(),myrot)*RAD_TO_DEG) > 45.0) { blah; }

versus this kind of construct:

fTheta = llAngleBetween(llGetRot(), myrot) * RAD_TO_DEG;
if (fTheta > 45.0) { blah; }

There is an obvious advantage in the latter, however.

From: someone
coincidental integer test for zero = false are also pretty easy to redefine in the integer sense rather than doggedly trying to fit them to the local syntax of TRUE/FALSE, and possibly more useful.


Making all conditionals into booleans isn't "local" by any means. Almost all typed languages have booleans, and allow boolean expression evaluation. Coding for "proper" boolean expressions won't hurt anyone there.

Example:

if (iFlags & 0x1000) { blah; }

shouldn't generate any more code (or very little in the most unoptimized case possible) than

if ((iFlags & 0x1000) != 0) { blah; }

and the latter makes more logical sense (at least to me), is more portable, etc.
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-29-2009 20:32
From: Talarus Luan
Well, let's do the math..
[...]16 bytes savings per 4k, that would be 64 bytes savings per script, times 3000, would be a whopping 192k. OK, then let's say it is 5 times that. That amounts to just under the huge size of ONE megabyte. Wow. That's a lot!

Not really.

ok, you say not much, I say +234 scripts worth of data. which could be a big deal if the scripts being added are yours...

I'll grant back filling isn't going to take place, and those savings may only matter in space terms if they are near to being over a page limit. but you also have the effect that almost all of these things are smaller because they use less compiled instructions, so they also run faster, taking less instructions to run the same code. given the case of a fully loaded frame with instructions being parsed from multiple scripts, the one using less instructions certainly runs faster, perhaps not as noticeably under a light load, but certainly as time dilation goes up either from heavy load or physics or other conditions.

but lets have a real world example...
ref:
my original function 219 bytes, the version we got out of it 174 bytes. net savings >20% of the original. Even if you can squeeze only half of that out of an average script it's still triple your conservative estimate, triple the total space, and triple the change of avoiding a page limit, nevermind the reduced instructions.

CODE

if ((fTheta=llAngleBetween(llGetRot(),myrot)*RAD_TO_DEG) > 45.0) { blah; }

// versus this kind of construct:

fTheta = llAngleBetween(llGetRot(), myrot) * RAD_TO_DEG;
if (fTheta > 45.0) { blah; }


to me I get the same information, but in truth the second feels literally repetitive as a read it. personally, I'd have little trouble finding it... additionally it's a very useful construct in the case of

CODE

while ((variable = function( value )) > constant){
//-- some code
}

//-- vs

variable = function( value );
while (variable > constant){
//-- some code
variable = function( value );
}


From: someone

if (iFlags & 0x1000) { blah; }

shouldn't generate any more code (or very little in the most unoptimized case possible) than

if ((iFlags & 0x1000) != 0) { blah; }

and the latter makes more logical sense (at least to me), is more portable, etc.

sadly the second does generate more code (I'm assuming you meant the statements to be reversed). I'll agree that the second is more explicit, but unnecessary given the language features. I literally read them as "if some bits in here match some bits in there" and the != 0 tacked on reads like "and some bits match".

personally I don't see that being a portability issue, going from concise to verbose when you know the new language requires it. it MIGHT speed up automated conversion, but in most of those cases you'll get tripped up by stupid things like syntax changes, or core behaviors like order of execution. nevermind that automated porting of lsl scripts tiny as they are is unlikely to speed the process much, even with optimally portable code.

but if it what I say doesn't work for the next person, by all means, go with what does. for all I know it's down to synesthesia on my part.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Talarus Luan
Ancient Archaean Dragon
Join date: 18 Mar 2006
Posts: 4,831
12-30-2009 10:23
From: Void Singer
ok, you say not much, I say +234 scripts worth of data. which could be a big deal if the scripts being added are yours...


*shrug* Wouldn't bother me in the least. There are certainly FAR bigger "efficiency fish" to fry before I would start worrying over a fraction of a percentage of waste, compared to the gains. I'm the last person that is going to begrudge someone a tiny bit of inefficiency for maintainability/portability/readability of their code.

From: someone
I'll grant back filling isn't going to take place, and those savings may only matter in space terms if they are near to being over a page limit. but you also have the effect that almost all of these things are smaller because they use less compiled instructions, so they also run faster, taking less instructions to run the same code. given the case of a fully loaded frame with instructions being parsed from multiple scripts, the one using less instructions certainly runs faster, perhaps not as noticeably under a light load, but certainly as time dilation goes up either from heavy load or physics or other conditions.


This is hardly true at all.

Take the case where such methods are used in a script that only happens occasionally (at most, like when a user types a specific command) versus the "most efficient" script possible that is often running 1,000 iterations a second. It all depends on what one is doing. I have also stipulated that, under certain conditions, taking advantage of said efficiency MAY be necessary. However, that latter situation is a rare case indeed, at least in all the LSL code I have ever written in 4 years, the most prominent example being WarpPos. It simply doesn't make any sense to grouse over a couple cycles of "inefficiency" that occur in trillions to quadrillions of others.

From: someone
but lets have a real world example...
ref:
my original function 219 bytes, the version we got out of it 174 bytes. net savings >20% of the original. Even if you can squeeze only half of that out of an average script it's still triple your conservative estimate, triple the total space, and triple the change of avoiding a page limit, nevermind the reduced instructions.


Beyond the fact that you're comparing apples to oranges (with respect to the "triple" comment, at least)...

Beyond the fact that the code in your OP in that thread doesn't even COMPILE (which goes back to a previous argument I recall)...

I have similar code which uses up 113 more bytes than your OP example (after I fixed yours to compile). However, it also allows me to do the same thing with just floats, which, in just about every application I have written that uses that kind of code (most often in data input verifiers which verify BOTH vectors AND floats), I would only save _30_ bytes with the final, "optimized" version. The differences being that: 1) It wouldn't take me an hour to decipher that mess in case I had to debug it or code using it that someone else wrote, 2) depending on the value of TRUE being 1 is FAR from portable (especially depending on implicit typecasting not becoming a factor (integer * float -> integer) at some later point), and 3) has functionality yours doesn't have (lower bound specification, float tests as well as vector tests).

In the case of the final, optimized fVecRangeXY() function, the savings is 12 (that's TWELVE) bytes. I think the choice of which methodology is academic, for me.

Unless I am doing something highly memory critical, or speed critical, I would not use such a "highly optimized" function. Now, you can argue that "it's a library function!" and that my disagreements are moot because it is (supposedly) "widely used and tested", but beyond the fact that such a point is tangential to the reason I posted my list, that gives me little comfort for the rest of the issues I raise above. After all, if it is going to be a "library function", it might as well be made into an llFunction, and then the whole argument can be put to rest, because the responsibility for it is no longer mine, as it won't be in compilable code I have to write and maintain anymore.

I'd also like to point out at this juncture that the LSL VM allocates the FULL 16kb frame, whether all of it is used or not, so, as far as that VM goes, all of this hand-wringing over "memory savings" is, with regards to script limits, moot.

From: someone
CODE

if ((fTheta=llAngleBetween(llGetRot(),myrot)*RAD_TO_DEG) > 45.0) { blah; }

// versus this kind of construct:

fTheta = llAngleBetween(llGetRot(), myrot) * RAD_TO_DEG;
if (fTheta > 45.0) { blah; }


to me I get the same information, but in truth the second feels literally repetitive as a read it. personally, I'd have little trouble finding it...


Yeah, I get the same information too, but I have to spend more time parsing the first than I do the second (beyond the simple annoyance of looking at it; that's more a personal issue, but it still is an issue, for me). The more complex the expression, the more time it takes to parse and analyze, and the greater the chance that one would miss a subtle bug in it or miss some subtle context of usage.

From: someone
additionally it's a very useful construct in the case of

CODE

while ((variable = function( value )) > constant){
//-- some code
}

//-- vs

variable = function( value );
while (variable > constant){
//-- some code
variable = function( value );
}


Perhaps, but I find the second form significantly easier to parse and analyze. Not to mention that loop logic can often be reorganized so that such a construct isn't necessary in the first place.

From: someone
sadly the second does generate more code (I'm assuming you meant the statements to be reversed).


Actually, I meant "any more or less code". Those two statements SHOULD generate the same exact code, and do on most compilers which have even the simplest optimizations.

I'm aware that it doesn't on LSL2, but I will still use the latter construct exclusively over the other, unless I have a reason to use the former (like a LOT of those kinds of tests under very tight memory conditions, and all other less obfuscating optimization options exhausted).

From: someone
I'll agree that the second is more explicit, but unnecessary given the language features. I literally read them as "if some bits in here match some bits in there" and the != 0 tacked on reads like "and some bits match".


I'm not writing code "for the compiler" or "the language features". The language features serve me, not the other way around. If they don't serve me, they don't get used.

When I see the first construct, I see two integer operands and a bitwise integer operator and, that's it! My mind goes "that's an error.. no wait; that's that shortcut 'feature' again". The & operator isn't just for "matching bits", even in a conditional statement, ya know.

From: someone
personally I don't see that being a portability issue, going from concise to verbose when you know the new language requires it. it MIGHT speed up automated conversion, but in most of those cases you'll get tripped up by stupid things like syntax changes, or core behaviors like order of execution. nevermind that automated porting of lsl scripts tiny as they are is unlikely to speed the process much, even with optimally portable code.


Going from a language which allows such a shortcut to one which doesn't allow it is most certainly a portability issue, especially when you see people using multiple bitwise operators, as well as integer functions, the same way. Automated conversion would likely cause more problems with those kinds of statements than it would solve.

From: someone
but if it what I say doesn't work for the next person, by all means, go with what does. for all I know it's down to synesthesia on my part.


Well, considering I said in my OP that these are guidelines that *I* follow and have found useful, that's pretty much what I said, too. I only gave the reasons why I found them useful. If people don't find them useful, then, by all means, don't use them. It is not like I have any say over what anyone else does anyway -- that wasn't the point of me posting them. The point of sharing knowledge and experience (and whatever passes for wisdom in my head) was.

In cases where people are asking me for help with their scripts, I often even go to the extent of "normalizing" their code against a similar methodological template, as I actually solve their problems faster, even with the extra time spent normalizing it. Sometimes, I even solve their problems in the process of normalizing it, because of incorrect "use" of said "features". That also goes back to one problem I have with many programmers in general: People tend to learn things the "shortcut" way before they learn them the "right" way (ie, learning the "hows" before the "whys", if at all), and end up mowing my flowerbed with their lawn tractor (for example, when I am working on some kind of collaborative project, time-shifted or not).
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
12-31-2009 03:45
From: Talarus Luan
It simply doesn't make any sense to grouse over a couple cycles of "inefficiency" that occur in trillions to quadrillions of others.

point in fact, I specifically said above that it's not likely to matter, and that my reasoning was that it provides an option to greater efficiency and is a good habit to get into for it's cumulative effect.

From: someone
Beyond the fact that you're comparing apples to oranges (with respect to the "triple" comment, at least)...
so comparing a byte savings 16 bytes per 4k, vs 48 bytes (that's 3 times 16) in a 219 byte function is apples an oranges? personally I thought it more realistic to consider that 219 bytes as part of a full 4k that couldn't be optimized more... but at a strict comparison, assuming you could get the same savings over the entire 4k that would be ~820 bytes, or a little over 51 times your estimate... but like I said... not realistic.

From: someone
Beyond the fact that the code in your OP in that thread doesn't even COMPILE (which goes back to a previous argument I recall)...

and as you can obviously tell the difference was lost in an edit, or else neither I nor those who followed up would have been able to test it. FTR a function name got rewritten, which has absolutely nothing to do with our discussion here, but you knew that right? but since you brought it up I fixed it, just for you, even though it was obsolete code.

From: someone
I have similar code which uses up 113 more bytes than your OP example

that'd be 219 + 113 = 332.

From: someone
However, it also allows me to do the same thing with just floats,
[...]
3) has functionality yours doesn't have (lower bound specification, float tests as well as vector tests).

ok, so yours has more features, that's a good reason for it to be bigger, I agree. (FTR it's not mine, I only tweaked it.)

From: someone
In the case of the final, optimized fVecRangeXY() function, the savings is 12 (that's TWELVE) bytes. I think the choice of which methodology is academic, for me.

219 - 195(final open ranged version) = 24. which is still >10% savings, with an increase in functionality to boot.... so right now as it stands, your version and the optimal xy version differ only by the ability to conform a float by itself, and the additional 137 bytes used to do it right?
From: someone
I would only save _30_ bytes with the final, "optimized" version.

CODE

//-- 99bytes
float uClampFloatXY( float vFltLowBound, float vFltHighBound, float vFltTarget ){
if (vFltTarget < vFltLowBound){
return vFltLowBound;
}
if (vFltTarget > vFltHighBound){
return vFltHighBound;
}
return vFltTarget;
}

//-- 83bytes
float uClampFloatXY( float x, float y, float z ){
return (vFltLowBound < vFltTarget && vFltTarget < vFltHighBound) * vFltTarget
+ (vFltTarget > vFltHighBound) * vFltHighBound;
}

Apples to apples, savings of 38 to 54 bytes, even with the extra function header =) no need to thank me... =P

From: someone
The differences being that: 1) It wouldn't take me an hour to decipher that mess in case I had to debug it or code using it that someone else wrote,

solution, never write code beyond your own comprehension.
From: someone
2) depending on the value of TRUE being 1 is FAR from portable

personally I feel that kind of portability is overrated... to redirect a popular phrase here.. "port algorithms not code"

From: someone
(especially depending on implicit typecasting not becoming a factor (integer * float -> integer) at some later point),

actually I bore that in mind... which is why the integer values appear before the float values, since it's fairly standard for the operation to be cast as the latter type.






From: someone
I'd also like to point out at this juncture that the LSL VM allocates the FULL 16kb frame, whether all of it is used or not, so, as far as that VM goes, all of this hand-wringing over "memory savings" is, with regards to script limits, moot.

and I'll just as happily point out that when coming up against those memory limits, every scrap counts to avoid stack-heap collisions... but moreover, one of the main points of mono was supposed to be the collapsing of that space to 4k chunks, and that is part of LL's stated plan for script limits..

From: someone
Yeah, I get the same information too, but I have to spend more time parsing the first than I do the second (beyond the simple annoyance of looking at it; that's more a personal issue, but it still is an issue, for me).

we obviously have opposite reactions here... possibly because of reading style, or who knows what...

From: someone
Perhaps, but I find the second form significantly easier to parse and analyze. Not to mention that loop logic can often be reorganized so that such a construct isn't necessary in the first place.

I picked that particular polling loop because I've seen it frequently in certain applications. there really aren't any better options than inclusion or doubling when you need to test before running other code in a loop like that.

From: someone
Actually, I meant "any more or less code". Those two statements SHOULD generate the same exact code, and do on most compilers which have even the simplest optimizations.

complaining that mom usually does the laundry never got a college kids clothes any cleaner.

From: someone
I'm not writing code "for the compiler" or "the language features". The language features serve me, not the other way around. If they don't serve me, they don't get used.

to my mind you're writing your code for everybody else BUT yourself, by ignoring the "features" available to you... like using a wooden spade to dig with, when you could use a metal one... on the off chance your neighbor wants to borrow it, because he's not careful around buried power lines and might get shocked...

From: someone
When I see the first construct, I see two integer operands and a bitwise integer operator and, that's it! My mind goes "that's an error.. no wait; that's that shortcut 'feature' again". The & operator isn't just for "matching bits", even in a conditional statement, ya know.

but actually it literally is.... what you do with the result of that is up to you. in LSL context, if checks if there were any matches, != compares to check that it's different than the next value and so on... then again I read programming like a sentence, I don't read this world which is a noun, I just read the word, and process subconsciously that it needs to be a noun, and if it isn't, it jumps out at me like "the soft jumped on the table".

From: someone
Well, considering I said in my OP that these are guidelines that *I* follow and have found useful, that's pretty much what I said, too. I only gave the reasons why I found them useful. If people don't find them useful, then, by all means, don't use them. It is not like I have any say over what anyone else does anyway -- that wasn't the point of me posting them. The point of sharing knowledge and experience (and whatever passes for wisdom in my head) was.

at any level, that's all we can do, and was as much my intent as yours. we disagree on some points, and hopefully someone reading got something useful from the reasoning.

From: someone
In cases where people are asking me for help with their scripts, I often even go to the extent of "normalizing" their code against a similar methodological template, as I actually solve their problems faster, even with the extra time spent normalizing it. Sometimes, I even solve their problems in the process of normalizing it, because of incorrect "use" of said "features".

I'd have to say that a good 25% of scripts that I've had to look at and debug for beginners could be solved by indentation and whitespace alone. so I can relate.
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Talarus Luan
Ancient Archaean Dragon
Join date: 18 Mar 2006
Posts: 4,831
12-31-2009 16:13
From: Void Singer
point in fact, I specifically said above that it's not likely to matter, and that my reasoning was that it provides an option to greater efficiency and is a good habit to get into for it's cumulative effect.


..and avoiding it where not necessary (most cases) is a good habit to get into for its cumulative effect on readability and maintainability.

From: someone
so comparing a byte savings 16 bytes per 4k, vs 48 bytes (that's 3 times 16) in a 219 byte function is apples an oranges? personally I thought it more realistic to consider that 219 bytes as part of a full 4k that couldn't be optimized more... but at a strict comparison, assuming you could get the same savings over the entire 4k that would be ~820 bytes, or a little over 51 times your estimate... but like I said... not realistic.


No, the comparing apples to oranges part has to do with the fact that one is a single function, where the other is a general approach to conditional statements. The difference means that greater savings in one doesn't mean that it is better than lesser savings in the other, since the frequency of occurrence is different. IE, you can't directly scale the savings by comparison.

From: someone
and as you can obviously tell the difference was lost in an edit, or else neither I nor those who followed up would have been able to test it. FTR a function name got rewritten, which has absolutely nothing to do with our discussion here, but you knew that right? but since you brought it up I fixed it, just for you, even though it was obsolete code.


Well, the point is that you posted it as a bit of evidence that you probably expected me to look at. When I did so, I was taking MY time to do it. That I couldn't just drop it in a script and go, so I could get on to the analysis part wasted my time (and was a hassle, to boot). Something which is pertinent to this discussion for the "wasting time" and "hassle" parts.

From: someone
CODE

//-- 83bytes
float uClampFloatXY( float x, float y, float z ){
return (vFltLowBound < vFltTarget && vFltTarget < vFltHighBound) * vFltTarget
+ (vFltTarget > vFltHighBound) * vFltHighBound;
}

Apples to apples, savings of 38 to 54 bytes, even with the extra function header =) no need to thank me... =P


Doesn't even compile, so definitely no need. ;) Still isn't the same, either, sorry to say.

From: someone
solution, never write code beyond your own comprehension.


It has nothing to do with comprehension, it has everything to do with time.

I have no doubt I could hand you some code that would win an IOLSLCC, that compiles, and performs a specific, useful function, and you would have no trouble comprehending it -- in time.

From: someone
personally I feel that kind of portability is overrated... to redirect a popular phrase here.. "port algorithms not code"


It is a common equivocation. Porting algorithms is a different process with a different goal than making code portable. "Porting algorithms" implies "coding from scratch"; not necessarily a bad thing, but that isn't only what "portability" is about.

It is a good generalization for a form of "porting", but that doesn't eliminate the value of making the algorithms embodied in the code easier to "port" should you find yourself doing so one day.

From: someone
actually I bore that in mind... which is why the integer values appear before the float values, since it's fairly standard for the operation to be cast as the latter type.


I've not noticed operand order being any more or less a solution to that problem than operand type, or even result type.

Related point: One other practice I have learned, similar to always explicitly parenthesize, is to always explicitly convert if there is any potential for automatic conversion. More than likely, the compiler will get it wrong, or at least not do it the way you expect.

From: someone
and I'll just as happily point out that when coming up against those memory limits, every scrap counts to avoid stack-heap collisions... but moreover, one of the main points of mono was supposed to be the collapsing of that space to 4k chunks, and that is part of LL's stated plan for script limits..


In most scripts, even a 16k memory limit is far more than will ever be used. In the situation where it "counts", I've already stipulated to doing whatever needs to be done.

I'm well aware of "the main points of mono"; if this was about mono, then should you be using LSL VM code metrics to exemplify it?

From: someone
we obviously have opposite reactions here... possibly because of reading style, or who knows what...


I doubt we're alone in either position...

From: someone
I picked that particular polling loop because I've seen it frequently in certain applications. there really aren't any better options than inclusion or doubling when you need to test before running other code in a loop like that.


*shrug* I've written thousands of scripts in LSL at this point; not only do I not use that loop construct, I haven't yet had to deconstruct it the way you did. Obviously, it doesn't come up that often as a problem.

From: someone
complaining that mom usually does the laundry never got a college kids clothes any cleaner.


Not sure what that has to do with anything I said, but OK, whatever.

From: someone
to my mind you're writing your code for everybody else BUT yourself, by ignoring the "features" available to you... like using a wooden spade to dig with, when you could use a metal one... on the off chance your neighbor wants to borrow it, because he's not careful around buried power lines and might get shocked...


Then you're not understanding what I am saying. I've found that using a metal spade with a fiberglass handle is good for digging around, whether there are buried utilities around or not, and am saying so. There are some really nice metal-handled shovels in the toolshed that are very sturdy and might make my digging slightly more efficient, and I know well how, when, where, and why to use them, but I think I will stick with what I have for common use. It most definitely has reduced my "time waste" and "hassle factor". :)

From: someone
but actually it literally is.... what you do with the result of that is up to you.


No, literally, it is a bitwise AND operation. What YOU do with the result of that is up to you.

From: someone
in LSL context, if checks if there were any matches, != compares to check that it's different than the next value and so on...


No, in LSL context (as in most other languages), it still does a bitwise AND operation, which just so happens to be a convenient way to check to see if one or more bits are set. The result is NOT a boolean value, it is an integer value. People who learn algorithms would normally expect it to be == TRUE, but it can't be (except in the specific case of "x & 1";). THAT is why, in my head, I go "error...". To me, it is the same thing as reading "if (1 - bFlag)". It makes no more sense than that (hopelessly valid in C / LSL) construct. Strangely enough, I have even seen "professional" programmers use that as an equivalent to "!x".

Strife's LSL optimizations use a lot of those similar kinds of optimizations. When I have to, I use some of them, too, but I avoid them like the plague everywhere else.

From: someone
then again I read programming like a sentence, I don't read this world which is a noun, I just read the word, and process subconsciously that it needs to be a noun, and if it isn't, it jumps out at me like "the soft jumped on the table".


I write programs like I am writing narrative, as much as possible, anyway. If I can't then read them back like that, then something is wrong.

I think one crux of the problem is that you like (or don't mind) living with implicits, and I only like living with explicits, because my experiences with implicits leads me to believe that "going the extra mile" is a preventative measure that, in most cases that *I* have encountered, is worth the cost of a little inefficiency. Not that there should be any extra inefficiency introduced as a result of using explicits, it just so happens because compiler writers and language designers get sloppy and assume everyone is comfortable with their own take on what the implicits should be.

It is really kinda funny in a way, too. As IT professionals, we tell everyone "The computer does EXACTLY what you tell it to do, so if you tell it something ambiguous, the result may also be ambiguous, or at least not what you wanted or expected". Then we go and write code which has ambiguities embodied in assumptions and implicits, and we wonder why programs and operating systems have so many bugs related to that EXACT SAME problem.

From: someone
at any level, that's all we can do, and was as much my intent as yours. we disagree on some points, and hopefully someone reading got something useful from the reasoning.


I don't mind disagreements, but debasing my own experience on principle is going to get "resistance". ;)

From: someone
I'd have to say that a good 25% of scripts that I've had to look at and debug for beginners could be solved by indentation and whitespace alone. so I can relate.


Eh? O.o
1 2 3