New list of my functions, with some questions

Discuss your code, get questions answered

New list of my functions, with some questions

Postby d_motto » Thu Jul 26, 2012 8:37 pm

I have a new list of some of my functions, with some questions:

Question 0: Are any of these of interest in being included in the Number Theory or other shared folders?

Question 1: I know I can use
Code: Select all
"number" Tools.checkType

in an RPL/RPL+ program, or
Code: Select all
Tools.checkType(x, "number")

in a JavaScript function.
But can I use more than one test, to allow for both "numbers" and "bignum" as input for example?

Question 1A: I am attempting to document the TYPE and typeof results with various ND1 types, and they match up fairly well with the HP50G AUR TYPE results. I haven't been able to generate each type, though.
Here is my listing (50G TYPE followed by spaces, then ND1 typeof, then a space and a hyphen and a space, then the 50G name for the TYPE.
At the end are some other types and what the TYPE number returns. Some vectors return different TYPE numbers, as well.

TYPE typeof
50G ND1 - 50G name
---------------------------------------------------------------------
0 number - Real Number
1 complex number - Complex Number
2 string - String
3 - Real Array
4 vector - Complex Array
5 - List
6 expression or name - Global name
7 expression or name - Local Name
8 RPL program - Program
9 expression or name - Algebraic Object
10 binary number - Binary Integer
11 - Graphics Object
12 tagged - Tagged Object
13 - Unit Object
14 - XLIB Name
15 - Directory
16 - Library
17 - Backup Object
18 - Built-in Function
19 - Built-in Command
20 - System Binary
21 - Extended Real
22 - Extended Complex
23 - Linked Array
24 - Character
25 - Code Object
26 - Library Data
27 - Minifont
28 bignum - Real Integer
29 - Symbolic Vector/Matrix
30 - Font
31 - Extended Object

fraction 9
boolean 0
CF (continued fraction) -1
matrix
bigfloat -1
function (JS function) -1

Question 2: Some built-in functions return regular numbers up to a certain point, then return BigInts afterward. Can I program that? An example is the Catalan number; it should return an integer result, but for 14, it returns 2674440.00000001 (when it should be 2674440 exactly; 17 returns 129644789.999999 and should be rounded up. Larger inputs return numbers of the form 1.23e+59.

Essentially, I want to use BigNum calculations in JavaScript using the factorial function, but I get an "undefined function" instead.

About the programs:
I created the Anot, Aor, Aand and Axor commands to match the functionality of similar functions on the HP50G; you can use the AND, OR, NOT and XOR there on strings. Pretty fun.

Here are my updated programs:

'Factors' (from factors, which returns a set of factor/exponent pairs, creates an expanded list of prime factors, leaving original number on stack)
Input: number
Output: vector

Code: Select all
≪ RECT @dup factors toElements 2. / { } 1. ROT START DUP 1. 4. ROLL START PICK3 + NEXT NIP NIP NEXT≫


'Derange' (returns number of derangements or subfactorial, where each item is in a different position from original.)
Input: number

Code: Select all
≪ abs int factorial e / 0  round≫


'Collatz' (RPL + version)
Input: number

Code: Select all
≪ @dup IF isEven THEN 2 / ELSE 3 * ++ END≫


'Ulam' (computes number of Collatz steps to reach 1)
Input: number

Code: Select all
≪ 0 OVER DO Collatz SWAP 1 + SWAP UNTIL DUP 1 SAME END DROP SWAP≫


'UnitDivs' (number of unitary divisors: gcd(n,n/d) = 1)
Input: number

Code: Select all
≪ divs @dupdup reverse 2 ≪ gcd≫ DOLIST ≪ 1 ==≫ select≫


'Digits' (vector of digits of number)
Input: number

Code: Select all
≪ split [isInt] filter≫


'DblFact' (double factorial)
Input: number

Code: Select all
function (x) {     
  var d = 1;
  if (x < 2) return d;
  var i = x;
  while (i > 0) {
      d = d * i;
      i = i - 2;
  }
  return d;
}


'Diffs' (successive differences of a vector, one entry shorter than the input vector)
Input: vector

Code: Select all
≪ @dup tail 0 + - @dup size 1 - resize≫


'ageme' (number of days since I was born)

Code: Select all
function () {     
  var monthArray = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
  var today = new Date();
  var bmo=today.getMonth();
  var d2a = monthArray[bmo] + ' '
      + today.getDate() + ', '
      + today.getFullYear() ;
  var s2 = Date.parse ( d2a );
  var s1 = Date.parse ( "[color=#FF0000]Insert DOB here as Month, dd, yyyy[/color]" );
  var dayDiff = Math.abs(Math.round((s2-s1)/86400000))
return dayDiff;
}


'cool' (cool things about input number)
Input: number

Code: Select all
≪ =n "Nxt" n nextPrime @tag "Prv" n prevPrime @tag "Divs" n ndivs @tag "Phi" n phi @tag "Rdcl" n radical @tag "sigma" n 1 sigma @tag "Hex" n toHex @tag "Oct" n toOct @tag "Ulam" n Ulam @drop @tag n Factors ≫


'PartConj' (conjugate of a partition; reading a Ferrers diagram vertically instead of horizontally)
Input: vector

Code: Select all
≪ @dup =v [] =a 1 at 1 - 0 @swap FOR x v ≪ x > ≫ map total a @swap + =a NEXT a≫


'Period' (not perfect - supposed to return the period of a repeating decimal fraction; works for primes and some composites but not all)
Input: number

Code: Select all
≪ =n n @dup 1 - 1 @swap FOR x 10 x n modpow @dup 0 IF == THEN @drop "=terminates" @tag BREAK END IF 1 == THEN x "=period" @tag BREAK END NEXT≫


'Egypt' (gives vector of denominators of input proper fraction; the last entry is returned as a fraction)
Input: fraction

Code: Select all
≪ @dupdup [ ] =n inv @dup WHILE isInt NOT REPEAT 1 + int @dup n + =n inv - @dup inv @dup END n + @drop2nd reverse≫


'UniqFactors' (unique prime factors of number)
Input: number

Code: Select all
≪ Factors removeDuplicates≫


'toBinv' (convert integer to binary vector)
Input: number

Code: Select all
function (x) {   
  var b = x.toString(2);
  var a = split(b);
  return a;
}


'SumBits' (compute the sum of binary bits in the number; leave original number on stack)
Input: number

Code: Select all
≪ @dup toBinv total≫


'Anot' (NOT an ASCII string)
Input: string

Code: Select all
function (y) {     
  y = calculator.unquote(y) ;
  x = "" ;
  for (i=0;i<y.length;i++) {
      x += String.fromCharCode((~ y.charCodeAt(i)) & 255) ;
  }
  x = "\"" + x + "\"" ;
  return x ;
}


'Axor' (XOR two ASCII strings)
Input: two strings

Code: Select all
function (y, z) {       
  y = calculator.unquote(y) ;
  z = calculator.unquote(z) ;
  ly = y.length ;
  lz = z.length ;
  if (lz>ly) {
        y += new Array(lz + 1).join(" ").slice(0,lz) ;
  }
  if (ly>lz) {
        z += new Array(ly + 1).join(" ").slice(0,ly) ;
  }
  x = "" ;
  for (i=0;i<y.length;i++) {
      x += String.fromCharCode((y.charCodeAt(i) ^ z.charCodeAt(i)) & 255) ;
  }
  x = "\"" + x + "\"" ;
  return x ;
}


'Aor' (OR two ASCII strings)
Input: two strings

Code: Select all
function (y, z) {       
  y = calculator.unquote(y) ;
  z = calculator.unquote(z) ;
  ly = y.length ;
  lz = z.length ;
  if (lz>ly) {
        y += new Array(lz + 1).join(" ").slice(0,lz) ;
  }
  if (ly>lz) {
        z += new Array(ly + 1).join(" ").slice(0,ly) ;
  }
  x = "" ;
  for (i=0;i<y.length;i++) {
      x += String.fromCharCode((y.charCodeAt(i) | z.charCodeAt(i)) & 255) ;
  }
  x = "\"" + x + "\"" ;
  return x ;
}


'Aand' (AND two ASCII strings)
Input: two strings

Code: Select all
function (y, z) {       
  y = calculator.unquote(y) ;
  z = calculator.unquote(z) ;
  ly = y.length ;
  lz = z.length ;
  if (lz>ly) {
        y += new Array(lz + 1).join(" ").slice(0,lz) ;
  }
  if (ly>lz) {
        z += new Array(ly + 1).join(" ").slice(0,ly) ;
  }
  x = "" ;
  for (i=0;i<y.length;i++) {
      x += String.fromCharCode((y.charCodeAt(i) & z.charCodeAt(i)) & 255) ;
  }
  x = "\"" + x + "\"" ;
  return x ;
}


'Lucas' (Lucas number from sequence 1,3,4,7,...)
Input: integer

Code: Select all
function (n) {   
    Tools.checkType(n, "number") ;
    var j=BigInteger.ONE ;
    var k=BigInteger.THREE ;
    if (n == 0) {
      var x = BigInteger.ZERO ;
    }
    else  if (n == 1) { 
        var x = j ;   
    } 
    else  if (n == 2) { 
        var x = k ;   
    } 
    else
        for (var i=2; i<n; i++) {
            x = BigNum["+"](j, k) ;
            j = k ; 
            k = x ; 
    }
return x ;
}


'Bell' (Bell number: number of non-empty sets)
Input: integer

Code: Select all
function (n) {       
  var b = [];
  var j, k, a ;
  b[0] = 1 ;
  b[1] = 1 ;
  a = 1 ;
  if (n>1) {
      for (j=2; j<=n; j++) {
        a = 0 ;
        for (k=0; k<j; k++) {
            a += (b[k]*calculator.functions.combinations(j-1,k)) ;
        }
      b[j] = a ;
      }
  a = b[n] ;
  }
  return a ;
}


'Catalan' (answers to many counting problems)
Input: integer
Code: Select all
function (n) {     
  var c = ME.factorial(2 * n) / (ME.factorial(n + 1) * ME.factorial(n)) ;
  return c ;
}


David Motto
d_motto
 
Posts: 35
Joined: Tue Apr 17, 2012 9:19 am

Re: New list of my functions, with some questions

Postby oliver » Fri Jul 27, 2012 7:41 am

Hi Dave,

Question 0: Are any of these of interest in being included in the Number Theory or other shared folders?


Absolutely. I meant to approach you and ask you about that. :-)

But can I use more than one test, to allow for both "numbers" and "bignum" as input for example?

I am attempting to document the TYPE and typeof results with various ND1 types...


Wow. Nice work. Thank you for sharing!

The questions you're raising are super important and the documentation has been thin on that, so I wrote up two notes that I hope answer your questions:
For JS: http://forums.naivedesign.com/viewtopic.php?f=2&t=668
For RPL: http://forums.naivedesign.com/viewtopic.php?f=9&t=669
I hope you approve that I used and completed your table. Thanks again for this work and table! It's great.

I'll edit this post a little later or tomorrow and reply to the rest of your items.
Great work on the programs!

Cheers,

Oliver
oliver
Site Admin
 
Posts: 433
Joined: Sat May 01, 2010 2:11 pm

Re: New list of my functions, with some questions

Postby oliver » Fri Aug 03, 2012 1:43 am

Dave,

So. Thanks again for sharing this cool collection of programs!

I'm more than happy to include them in the Number Theory folder. Please upload your folder and let me know your sharing ID (displayed under ND1 in the Settings App) per PM (personal message).
Also, if you could post an update note, listing your programs for the Number Theory folder in the Downloadable Folders section, that would be great. Even better, if each came with an example.

I'd like to exclude from this folder two functions, as they don't directly relate to Number Theory: ageme and cool.
We should find a different place for them. Maybe it's time to start a Goodies folder with a colorful variety of programs such as this.

Some feedback:
ageme: guess this would be nicer if it would accept your b-day from the stack or you could enter your b-day. The Date object will happily parse various ways of writing a date, and INPUT could be used to get a string from the user.
Digits: are you sure there's value in having a number 2.43e27, sequestered as [2 4 3 2 7]? What would you do with the digits of such a number. (To me, applications of getting the digits of a non-Integer seem unlikely.) The filter step is more expensive than the split. (Which doesn't matter on one number, but on a few thousand.)
Catalan: you shouldn't need the ME. prefixes in the code. (Though they don't hurt either.)

I'm really looking forward to trying all the programs out! It's great to see that you're programming in both languages!
Altogether, a great job!

Cheers,

Oliver
oliver
Site Admin
 
Posts: 433
Joined: Sat May 01, 2010 2:11 pm

Re: New list of my functions, with some questions

Postby d_motto » Mon Aug 06, 2012 6:45 am

Thank you for the reply. I have been looking at my programs and have managed to find a few bugs in them, not the least of them being the use of "i" for an index in the JavaScript programs (which interferes with the value of "i" as the square root of -1); I a have changed the index and incorporated the "/* as is */" into the programs in case other letters come into play.

My alphanumeric logic functions don't belong in a number theory folder, as well, but they had bugs in them and have been rewritten.

One thing I would like to be able to do is be able to handle BigInts automatically: to switch to them as needed and avoid rounding errors... Not an easy task, I think.

I would also like to build in the ability to handle different kinds of input for some functions: to use integers, reals and vectors for example - very much a difficult task.

Perhaps these programs could be a starting point for someone to build on?

As for Digits, I am in a quandary about this. I could use the Mantissa of a number to avoid digits from the exponent, but if I have 123000, I would end up with [1 2 3] that way and am not certain what I really want.

I am going to take a bit of time thinking about things like this, but will upload a fixed folder and send you my ID privately in a few weeks.

Dave Motto
d_motto
 
Posts: 35
Joined: Tue Apr 17, 2012 9:19 am

Re: New list of my functions, with some questions

Postby d_motto » Sun Aug 19, 2012 8:54 pm

More about Digits: I was thinking about how something like this might be used. If a number like 150000 was entered, you would want to get a vector of six digits from it, including the zeroes, and if a number like 1.50000 was entered (using . as a radix, not like the , in some other countries), you might want a vector of the two significant digits. That points to the idea that perhaps the mantissa function might be involved for numbers like 6.02e+23, giving a vector like [ 6 0 2 ], where my function would return [ 6 0 2 2 3 ].

So, I started to look at how to do this: loop through the number and see if I reach an "e", then stop? Or look at the size of a number and use the mantissa function if it is greater than or equal to 1.0e+15?

That is when I found something peculiar: if you enter 10 (enter) 15 ^ 1 - you get 999,999,999,999,999 s a number, but if you enter 15 nines, you get a "bigint" instead, which behaves differently (divide it by 10 a few times and see).

Not certain if this is a bug or a feature.

So, I am Still not sure what I want to do with this...

One other thing: I don't know what kind of memory constraints there are with ND1, but my version of the program Diffs that returns the successive differences between adjacent numbers in a vector is much quicker with large vectors (say, of 500 numbers) than the diffsOfVec program in the Examples folder. Not that I am bragging (although my program returns the opposite signs from that one); I was surprised that there was a difference.

I am working on the writeup and examples, and wrote an 'AgeYou' program that takes a date string from the stack.

Dave Motto
d_motto
 
Posts: 35
Joined: Tue Apr 17, 2012 9:19 am

Re: New list of my functions, with some questions

Postby d_motto » Sun Aug 19, 2012 8:57 pm

One more thing: I still don't know if I can do things like some programs/functions do: automatically switch over to BigNum or BigInt when a result gets to be a certain size. Is there a way to do that, that mere mortals can get to, or is that deeper than we can handle?

Dave Motto
d_motto
 
Posts: 35
Joined: Tue Apr 17, 2012 9:19 am

Re: New list of my functions, with some questions

Postby oliver » Sun Aug 26, 2012 1:45 pm

Hi Dave,

Re Digits, how about this?
Code: Select all
<< =:num
   IF isInt
   THEN split
   ELSE mantissa split
>>


Yes, if you enter a 15+ digit number it's automatically promoted to a BigInt. However, using the ^ operator will never do that to a real.
However, if you promote one of the operands to a BigInt prior to applying the ^ operator, the result *will* be a BigInt.
Code: Select all
<< 10 toBig 15 ^ 1 - >>


And that, really, is the recipe to dealing with BigInts, at least in RPL: have the input drive the computation and the output, and your same algorithm will work with both Reals and BigInts, without extra coding involved.
So, this simple program
<< 15 ^ 1 - >>
will work with both Real and BigInt input, for example.

Some functions automatically promote to BigInts for results, and if *your* implementation uses these functions, then you too will have this automatic promotion as a feature of your code.
For example, since "!" has automatic promotion, this implementation of Catalan would produce Real or BigInt output, depending on the magnitude of the input Real. (And the code will also work with BigInt input.)
<< =n 2 n * ! n 1 + ! n ! * / int >>
(Note the use of int in place of round, which is not be defined on BigInts.)

This may still not do what you want because the calculation will produce larger values than ! alone, and you'd rather have it change sooner over to BigInt. Let's say you'd like to switch over at 29.
You can do this as follows:
Code: Select all
<< =n
   IF n>=29 THEN toBig END
   2 n * ! n 1 + ! n ! * /
   int
>>


RPL+ has two advantages over JavaScript: the syntax works with types other than Reals, and code is usually shorter.
Note that if you use no loops, code fragments, and stick to built-in functions, there's *no* speed penalty for RPL+. That is "!" in RPL+ runs as fast as ME.factorial() in JavaScript. (In fact, "!" simply invokes ME.factorial() or BigNum.factorial().)

Automatic promotion in JavaScript will require you to use a) type checking and b) write type-specific code (here: BigNum code).
Example:
Code: Select all
function(n) {
    if (calculator.typeOf(n) == "bignum")
        return BigNum.factorial(BigNum["*"](BigInteger.TWO, n));
    else
        return ME.factorial(n * 2);
}


You find much more about type checking here: http://forums.naivedesign.com/viewtopic.php?f=2&t=668

User functions take any type and you have to check for the type of your input to work with multiple input types, and also to protect your function from being run on a "wrong" type. If you ever get to the point where you produce an extension, the selection of the correct implementation for a given type is done for you. This actually adds convenience and also makes sure your function is not invoked with a wrong type.
Here's how one could implement Catalan as extension functions for both Reals and BigInts:
Code: Select all
/* Catalan as system function */
ME.catalan = function(n) { return this.int(this.factorial(n*2)/(this.factorial(n+1)*this.factorial(n))); };
BigNum.catalan = function(n) { return this.int(this.factorial(this["/"](this["*"](n, BigInteger.TWO), this["*"](this["+"](n, BigInteger.ONE), n))); };


Two more benefits of this approach: your function(s) work in any folder. (They're indistinguishable from built-in functions.) And they will use vector processing. So,
Code: Select all
<< 1..10 catalan >>

would work, for example.

(This is described elsewhere but, in a nutshell, to do an extension you write code like shown which will enter as a Code object, and then inject into the calculator with the inject command. Usually, you'd have your code object named .injection (the dot hides it from the user) and have an Install button that has code like this << "MyExtension" .injection inject >>.)

To add switching over to BigNum for a real >= 29, you'd write
Code: Select all
ME.catalan = function(n) { return (n >= 29 ? BigNum.catalan(n) : this.int(this.factorial(n*2)/(this.factorial(n+1)*this.factorial(n)))); };


Hope all this makes sense.

Memory constraints: depends on your device, but you easily have at least 10-20 MB available. Much more on a later device. Pretty good for a "calculator".
The reason why your Diffs program is faster than diffsOfVec is that your implemention is a lot smarter. You're using functions that move all the run-time into JavaScript, whereas the DOSUBS code requires repeated invocation of RPL code, which is a lot slower.

Cheers.

Oliver
oliver
Site Admin
 
Posts: 433
Joined: Sat May 01, 2010 2:11 pm

Re: New list of my functions, with some questions

Postby d_motto » Sun Aug 26, 2012 8:02 pm

Oliver,

Thank you for the reply. I chose my screen name for the folder name not completely from vanity but because I thought you would take the good things from it, improve them, and forget the rest. Thank you for making it available for others.

I am learning more and more about this marvelous app, and it makes me want to rewrite all of my programs, some day, but...

I tried the program
<< mantissa split >>
on the number 12345 and got [1 2 3 4 5 0 0 0 0 0 0 0 0 0 0 0 2], so I don't think I want do do that.

Nice idea, though.

The Catalan function is more like:

<< =n 2 n * ! n 1 + ! / n ! * / >>

The int is not needed, but the problem is that 17 gives a result of 129644789.99998, so int would give the wrong number in the last two digits; that is why I used round. However, I don't see it switching to big numbers automatically at 29 (58 ! is over 2.35e78), so unless I come up with a different formula, I won't see an improvement in accuracy.

As for the vector differences, I just thought that my way was a different approach that the other way, and I have done some APL and J programming for fun, so I used a different method. The fact that it was "smarter" reminds me of the line from Lou Costello during the "Who's on first?" bit when Bud Abbott says that he is right: "I don't even know what I'm talkin' about!"

Cheers,

Dave Motto
d_motto
 
Posts: 35
Joined: Tue Apr 17, 2012 9:19 am

Re: New list of my functions, with some questions

Postby d_motto » Mon Aug 27, 2012 9:01 am

Oliver,

I found a better formula for the Catalan number, and have a new function:

<< =:n IF n >=25 THEN toBig END
@dupdup 2 * @swap combinations @swap 1 + / >>

Which is the combinations(2n,n)/(n+1), and starts to return a non-integer at n=25 (ends in .96). This takes a little time to process, as the combinations utility consumes some processing cycles (I assume).

This works pretty well, although I haven't checked the numbers beyond n=25.

I might put @dup in place of =:n and leave off the second n, to see if that helps. Is there an easy way for me to update the uploaded folder, or do you have to do that? Either way, I want to review some other programs before I do that.

Dave Motto
d_motto
 
Posts: 35
Joined: Tue Apr 17, 2012 9:19 am

Re: New list of my functions, with some questions

Postby oliver » Tue Aug 28, 2012 9:59 am

Dave,

The behavior of the mantissa function was faulty for certain integers (such as your 12345) and I have corrected this.
You can do "mantissa toPrecision" to get the correct effect today.

I'm contemplating having the command int take the effect of round(x, 0) for the next update, or having a new function "nearest".

Note, for immediate algebraics to work, there must be *no* space in them.
That is,
Code: Select all
IF n>=25 THEN ...

works, but
Code: Select all
IF n >=25 THEN ...

doesn't.

You may also write
Code: Select all
IF n 25 >= THEN ...

of course (which is standard RPL).

The shortest way to write this is
Code: Select all
n>=25 [toBig] IFT

by the way.

And, just In case: =n assigns local with the item on the stack, removing the item from it, whereas =:n does the same assign, but leaves the item on the stack.

I realized my suggested implementation of Digits lacked use of "num" and an "END".
Corrected:
Code: Select all
<< =:num
   IF isInt THEN num split
   ELSE num mantissa toPrecision split
   END
>>

Better, shorter:
Code: Select all
<< @dup
   isInt not [mantissa toPrecision] IFT
   split
>>

(With the next update, all the @-functions can be written without the "@" (which was a pain to type and looked bad). @-function are "catch-all" functions; that is, they operate on any type. I thought it was important to show that and also intended to discourage the use of stack functions (in favor of using locals), but at least the first part was a bad idea.)

However, when I actually typed this in, I realized the whole approach was stupid: 6.02e23 is seen as integer! (And it is: 6020000000...)
It's only not an integer after running mantissa on it.
You realized that already, which is why you looked into running mantissa on an integer.
Ok, so, the solution is now
Code: Select all
<< mantissa toPrecision split >>

and will be
Code: Select all
<< mantissa split >>

after the update. Phew! (Sorry, for posting untested code.)

Whenever you're ready to update your folder, upload with the "Visible to All" flag set to on and send me a PM, please. I'll have to copy it over, but this will become automated at some point for admitted folders.

Cheers.
oliver
Site Admin
 
Posts: 433
Joined: Sat May 01, 2010 2:11 pm


Return to Programming

Who is online

Users browsing this forum: Google [Bot] and 1 guest

cron