Mathematics

by Oasiscircle
Mathematics procs that BYOND doesn't include. Recommended for every project!
ID:1042127
 
Feel free to ask questions. I may add to this library in the future.
This library currently contains the following operations:
  • sum(list/l)
  • squaresum(list/l)
  • mean(list/l)
  • variance(list/l)
  • standarddev(list/l)
  • factorial(n)
  • nPr(n,r)
  • nCr(n,r)
  • integer(n)
  • sign(n)
  • deg2rad(n)
  • rad2deg(n)
  • pyth(a,b)
  • arcpyth(a,c)
  • triarea(a,b,C)
  • tan(n)
  • cot(n)
  • sec(n)
  • csc(n)
  • arctan(n)
  • arccot(n)
  • arcsec(n)
  • arccsc(n)
  • arctan2(x,y)
A few notes on extremely tiny optimization:

I've actually found in my ProcLib tests that sign is (oddly enough) faster this way:
proc/sign(n) return n && n / abs(n)

rather than using a ternary operator or a series of conditionals.

For converting to and from radians and degrees, you can keep a constant (180 * pi). For deg2rad, you multiply by (180 * pi), while for rad2deg, you divide by (180 * pi), so you might as well save the constant term.

Your integer() function uses a ternary operator, but == already returns 0 or 1.

I heard the ** operator is relatively inefficient in the case of x**2. Using x*x is apparently better, they say. You even do this in your arctan() and arccot().

Also (off the topic of optimization), Pythagorean's theorem works for any number of dimensions.
Couldn't some of the one-liners be #define macros? Make the compiler do some of the work... Unless it's getting extremely optimized byte code already.
In response to FIREking
The problem (the only one that comes to mind) is when you put expressions into #define macros.
#define sign(n) ((n) && (n) / abs(n))

src << sign(some crazy calculation)

// compiles as

src << sign((some crazy calculation) && (some crazy calculation) / abs(some crazy calculation))
In response to Kaiochao
Kaiochao wrote:
The problem (the only one that comes to mind) is when you put expressions into #define macros.
> #define sign(n) ((n) && (n) / abs(n))
>
> src << sign(some crazy calculation)
>
> // compiles as
>
> src << sign((some crazy calculation) && (some crazy calculation) / abs(some crazy calculation))
>


Ah so you'd have to use long form then.
Thanks for the optimizations, Kaiochao.
They've been added to the library.

I didn't know that the ** operator was relatively slow.
I know that the sqrt(n) proc is faster than doing n**0.5, I wonder why that operator is slower.
There's a lot of weird esoteric stuff here.

- The argument shouldn't be called 'n' when you're not expecting an integer (call it 'r' or 'x')
- Sign is written really weird, just check if the number is positive or negative
- pi180 is really redundant, and btw deg2rad and rad2deg don't work like that: you want to multiply by 180 and divide by pi to convert radians to degrees, and vice versa to convert back
- 'pyth' is an esoteric term and the proc itself is pretty useless... as a proc, since most of the time you either /want/ to see the sqrt(x^2+y^2) with your own eyes to make the application obvious or you don't want to take the sqrt at all
- arcpyth is pretty much a waste of space
- factorial should crash rather than return 0 when n is not an integer
- triarea is useless because you will very rarely have access both to a, b, and the angle between them and will usually calculate the area based on what is at hand
- squaresum is weird and situational, should probably do away with it
- same for counting permutations and combinations, factorial is enough (unless for some reason people use DM to do their combinatorics homework)
In response to Toadfish
My sign() returns -1, 0, or 1 depending on the sign. And as I said, it works faster than conditionals. If the number is 0, the AND fails and returns 0. Otherwise, it gives a "unit scalar" the same way unit vectors are found.
Okay, I can live with the unit vector (a scalar is a different thing) idea.
Can you add a proc that can order mobs based on a variable's number? I have mobs and they each have a speed. I want to make it so they are added to a list or something from the order of their speed from highest to lowest so that the faster you are the sooner your turn comes.
Na looks like that library can't do it
In response to Kaiochao
Kaiochao wrote:
A few notes on extremely tiny optimization:

I've actually found in my ProcLib tests that sign is (oddly enough) faster this way:
> proc/sign(n) return n && n / abs(n)
>

rather than using a ternary operator or a series of conditionals.
That is odd indeed. I wrote two different versions, and they're both faster than your version by about %10-15. Oddly enough(heh), it uses ternary operators as well.

sign_1(x) return (x < 0) ? -1 : (x > 0)
sign_2(x) return (x > 0) - (x < 0)

I guess DM's compiler is rather crappy at optimizing code.

EDIT: In newer versions, yours might(I haven't tested it yet) actually be faster since Lummox JR optimized abs() along with some other math functions.
runtime error: Division by zero
proc name: arctan2 (/proc/arctan2)
usr: (src)
src: null
call stack:
arctan2(-1, 0)
world: New()


That should return 180