Mathlib

mathlib:1.6
[size=+1]Math Library[/size]
Introducing Mathlib, a concise set of mathematical functions that aren't currently in ASH.
Some of these functions will be more useful than others in the given context, but the goal here was purely for fun. So, what does it do you ask? Why, let me show you.

string to_string(float number, int precision, boolean trailing)
string to_string(float number, int precision)

Simple extension to the existing to_string function, but with precision options, and, optionally, additional zeroes if there are less numbers after the decimal than the specified precision.

void throw(int error, string custom, boolean abort)
void throw(int error, string custom)
void throw(int error, boolean abort)
void throw(int error)

Error handler. Prints error messages based on error number, optionally add a custom message, and aborts if abort is set.

float fact(int x)
Standard factorial function. Throws an error if x is greater than 13, that's ASH's integer limit.

int bitSet(int x, int mask)
int bitUnset(int x, int mask)
int bitToggle(int x, int mask)

Modifying specific bits in integer x. Mask here refers to the the decimal value of the bits to modify, not the location. (i.e. to set LSBs 1 and 3, you'd pass mask "5")

int bitAnd(int A, int B)
int bitOr(int A, int B)
int bitXor(int A, int B)
int bitNot(int A)

The standard bitwise operators AND (&), OR (|), XOR (^), and NOT (~) for your bit manipulating pleasure. These functions were my main reason for starting this library, the rest just sort of fell in.

boolean flagSet(int x, int mask)
Checks x to see if the bits defined by mask are set.

boolean odd(int x)
Returns true if x is an odd number.

float sqrt(float x)
Returns square root of x.

float sin(float x, boolean deg, int prec)
float sin(float x, boolean deg)
float sin(float x, int prec)
float sin(float x)
float cos(float x, boolean deg, int prec)
float cos(float x, boolean deg)
float cos(float x, int prec)
float cos(float x)
float tan(float x, boolean deg, int prec)
float tan(float x, boolean deg)
float tan(float x, int prec)
float tan(float x)

All your basic trig functions.
Currently they are fairly accurate, but until I expand factorial to float, or mafia's float gets more accurate, precision seems to cap out around 8 decimal points.

float ln(float x, int prec)
float ln(float x)

Standard natural log function.

float mathlibeval(string expression)
float mathlibeval(string expression, float[string] variables)

My pride and joy. Similar to modifier_eval() and Zlib's eval() but with support for more standard functions and many of the functions included in mathlib.
While the trig functions can be passed with the degree boolean, it currently doesn't accept the precision parameter, and will merely ignore it.
Currently supports the functions included in standard modifier_eval() plus the following:
rand, fact, sin, cos, tan, throw, not, and, xor, or, and round.

Simply throw this in your script, and you're good to go:
Code:
import <mathlib.ash>

Thank you, I hope you enjoy and I hope at least one scripter puts this to use.
--Almighty Sapling

changelog
2010.11.26: file introduced
2010.11.26: trig functions complete. Added update feature and boolean odd(int)
2010.11.28: fact() changed; Added float mathlibeval(string,float[string]), float sqrt(float)
2010.12.09: Added float ln(float,int), boolean flagSet(int,int), minor change to version control.
2010.12.09: fixed my failure. I fail.
 

Attachments

  • mathlib.ash
    15.3 KB · Views: 41
Last edited:
Thank you for making this - looks really useful for certain scripting operations.

/me ponders what he could use this for...
 

StDoodle

Minion
I'd remove fact(), since it's of fairly limited use with the integer limit and all. Or possibly change it to use floats to allow for a decent range (you could even overload it so that it always used & returned floats, but accepted either).

Since radians is the standard to work with for trig, may I suggest two versions of each trig function? Ie sin(float) and sin(float, boolean) where the default for the boolean is false, and it means "use degrees"?

What do you mean by "power functions"? You can use a caret in ash to raise numbers to a power; were you talking about something else?

Also -- and sorry if this is cruel ;) -- I could see the use of a "mathlibeval()" function, that took a string, parsed it for mathlib functions, did them and turned the result over to mafia's eval() function.

All in all, looks pretty neat. I can think of a couple of times when this would have been handy to have, and I may well make use of it at some point.
 
Mafia has powers? Well then, that makes my life EASY as pie.

Trig functions will be up and running within the day thanks to you.

As for factorial, it's really only there because once I had powers, the Trig functions would be modified to use them. And allowing it to accept floats would be very fun mathematically for me (have you -seen- the Gamma function?)

Overloading the trig functions does seem easier than setting a variable.

And as for eval... that would indeed be fun for me. I'll start work on that tonight. Now if only there were pointers in ASH...
 

heeheehee

Developer
Staff member
Recursing might reduce code significantly -- observe:
Code:
int fact(int n) {
    if (n==0) return 1;
    return n*fact(n-1);
}

Technically, if you overload it to accept floats, you'd just need to change it to be the following:
Code:
float fact(float n) {
    n = floor(n);
    if (n==0) return 1;
    return n*fact(n-1);
}

And either way, we run into issues if we have a negative value supplied.

I had something similar to this, but I could never find any practical use in the scope of ASH scripting, so I never published it. And oh dear, there's lots of messy code that could be rewritten.
 

Veracity

Developer
Staff member
Now if only there were pointers in ASH...
Explain what you mean and how you'd use them. Pointers to what, in particular?
If you want function pointers, perhaps you should look at the "call" construct.
If you want pointers to data, think in Java, rather than C, and cope.

And hee^3: factorial is the standard example of a function that should NOT be written recursively, although you can. It's tail recursive, and is thus easily transformed into straight iteration...
 

heeheehee

Developer
Staff member
True, but space considerations are hardly an issue if we're never going to be calling it with a relatively large parameter -- we run into integer/float limitations before that happens. Now if we could use arbitrarily large integers and/or floats (not requesting this as a feature, since it'd just be unnecessary), that'd be a different story.
 
Technically, if you overload it to accept floats, you'd just need to change it to be the following:
Code:
float fact(float n) {
    n = floor(n);
    if (n==0) return 1;
    return n*fact(n-1);
}

Believe it or not, there is such thing as factorial on non-integers. It's a rather fun equation that would involve some calculus to solve, or inifinite products (but that takes a lot of iterations to get even close to accurate). I'm also going to have to agree with Veracity, just because you can make something recursive doesn't mean you should.
PS: My code isn't "messy". It certainly doesn't conform to industry standards, but it is consistent, which is all that's usually asked.

Pointers to what, in particular?
Data. My pointer request was for writing an equation parser. I can do it with recursion (I'll be posting a thread for help on that in a minute, something isn't working quite right) but when I last designed a calculator in a programming language it was very helpful to make a binary tree to tear apart the string into something that can be worked through and executed. I'm fine without having to do that though, the statement was made mostly in jest.
 
Last edited:
Also -- and sorry if this is cruel ;) -- I could see the use of a "mathlibeval()" function, that took a string, parsed it for mathlib functions, did them and turned the result over to mafia's eval() function.

Many painful days later, the wish is fulfilled. Anything else?
PS please test the shit out of this, I threw a few things at it, and it seems to work, but I don't trust my debugging efforts.
 
Top