Partial application to precompute intermediary results - functional-programming

For the below quardratic formula, I have multiple a but fixed b and c.
I wish to write a partial application function, which execute efficiently, i.e., my function doesn't recompute fixed values (because of b and c).
Here is my solution
let r b c = let z = b *. b in fun a -> (-.b +. sqrt (z-.4.0*.a*.c))/.(a*.2.0);;
I guess this solution can work, but I am not sure whether it is efficient enough. I just made b^2 to be fixed as I saw other parts are all with a.
Anyone can give me a better solution?

Yeah, that's a correct way to deal with the situation at hand. The alternate form doesn't help much (as long this obtains the accuracy you require). You may want to move the 4*c out as well,
let r b c = let z = b *. b and c4 = 4.0 *. c in
fun a -> (-.b +. sqrt (z-.a*.c4))/.(a*.2.0);;

Related

Using python to find the limit of a recusive function

Assume I had the following iterative fuction:
f(z) = z^2 + c
z initally equal to 0
and each answer of the function becomes z for the next iteration. i.e. if c is 1 then the fist iteration gives 1, the second gives 2 and so fourth.
Now assuming I already set a value for c, I would like to be able to use Python to find the limit as this function approaches an infinite number of iterations. How would I best be able to do that? Would Sympy be a good tool?
editied to clearify what I man by iterative function.

Modulo operator in decryption

I'm creating an encryptor/decryptor for ascii strings where I take the ascii value of a char, add 1 to it, then mod it by the highest ascii value so that I get a valid ascii char out.
The problem is the decryption.
Let's say that (a + b) % c = d
I know b, c, and d's values.
How do I get the a variables value out from that?
This is exactly the ROT1 substitution cipher. Subtract 1, and if less than lowest value (0 I assume, given how you're describing it), then add the highest value.
Using terms like "mod," while accurate, make this seem more complicated than it is. It's just addition on a ring. When you go past the last letter, you come back to the first letter and vice-versa. Once you put your head around how the math works, the equations should pop out. Basically, you just add or subtract as normal (add to encrypt, subtract to decrypt in this case), and at the end, mod "normalizes" you back onto the ring of legal values.
Use the inverse formula
a = (b - d) mod c
or in practice
a = (b - d + c) % c.
The term + c needs to be added as a safeguard because the % operator does not implement a true modulo in the negatives.
Let's assume that c is 2, d is 0 and b is 4.
Now we know that a must be 2... Or 4 actually.. or 6... Or any other even number.
You can't solve this problem, there are infinite solutions.

Julia : BLAS.gemm!() parameters

I want to use the BLAS package. To do so, the meaning of the two first parameters of the gemm() function is not evident for me.
What do the parameters 'N' and 'T' represent?
BLAS.gemm!('N', 'T', lr, alpha, A, B, beta, C)
What is the difference between BLAS.gemm and BLAS.gemm! ?
According to the documentation
gemm!(tA, tB, alpha, A, B, beta, C)
Update C as alpha * A * B + beta*C or the other three variants according to tA (transpose A) and tB. Returns the updated C.
Note: here, alpha and beta must be float type scalars. A, B and C are all matrices. It's up to you to make sure the matrix dimensions match.
Thus, the tA and tB parameters refer to whether you want to apply the transpose operation to A or to B before multiplying. Note that this will cost you some computation time and allocations - the transpose isn't free. (thus, if you were going to apply the multiplication many times, each time with the same transpose specification, you'd be better off storing your matrix as the transposed version from the beginning). Select N for no transpose, T for transpose. You must select one or the other.
The difference between gemm!() and gemv!() is that for gemm!() you already need to have allocated the matrix C. The ! is a "modify in place" signal. Consider the following illustration of their different uses:
A = rand(5,5)
B = rand(5,5)
C = Array(Float64, 5, 5)
BLAS.gemm!('N', 'T', 1.0, A, B, 0.0, C)
D = BLAS.gemm('N', 'T', 1.0, A, B)
julia> C == D
true
Each of these, in essence, perform the calculation C = A * B'. (Technically, gemm!() performs C = (0.0)*C + (1.0)*A * B'.)
Thus, the syntax for the modify in place gemm!() is a bit unusual in some respects (unless you've already worked with a language like C in which case it seems very intuitive). You don't have the explicit = sign like you frequently do when calling functions in assigning values in a high level object oriented language like Julia.
As the illustration above shows, the outcome of gemm!() and gemm() in this case is identical, even though the syntax and procedure to achieve that outcome is a bit different. Practically speaking, however, performance differences between the two can be significant, depending on your use case. In particular, if you are going to be performing that multiplication operation many times, replacing/updating the value of C each time, then gemm!() can be a decent bit quicker because you don't need to keep re-allocating new memory each time, which does have time costs, both in the initial memory allocation and then in the garbage collection later on.

Merge algorithm with arrays split in c>2 ways

As an example question we are asked to create a variant of merge sort where it splits array in to c>2 arrays of roughly equal size (when c = 2 it will use regular merge)
This is the solution:
cmerge(a1, a2, .... ac)
if c = 2 return Merge(a1, a2)
else
b1 = cmerge(a1, a2,...a(c/2), floor(c/2))
b2 = cmerge(a(roof(c/2)),... ac, roof(c/2))
return merge(b1,b2)
I understand where they got this solution but when it asks for the reccurrnce relationi get a bit confused. in the question they state c sorted arrays can be merged in O(n log c)
which makes the first case clear
T(n) = c(T(n/c)) + nlogc if n>= c
T(n) = theta(n^2) for n<c <----------- can someone explain where they are getting this?
I just reallly don't get where the n^2 is coming from. In the second case is there not just one call to MERGE? And merge is theta(n) if I remember.

Checking approximation of E

MathWorld page gives a simple numeric formula for e that's allegedly correct for first 10^25 digits. It states that e is approximately
(1 + 9^-4^(7*6))^3^2^85
Any idea how to check whether this formula is correct even for the first 10 digits?
Here's another way of writing the right hand side
Power[Plus[1, Power[9, Times[-1, Power[4, Times[7, 6]]]]], Power[3, Power[2, 85]]]
This problem does not need Mathematica at all. First, it is easy to show that 9^(4^(7*6)) is exactly equal to 3^2^85, since
9^(4^(7*6)) = 3^(2*4^(7*6)) = 3^(2^(1+2*(7*6))) = 3^2^85
Then, we know that one of the ways to represent e is as a limit
e = lim (1+1/n)^n, n->infinity
The only question is what is the error given that n is very large but finite. We have
(1+1/n)^n = e^log((1+1/n)^n) = e^(n*log(1+1/n)) = e^(1-1/(2n)+O(1/n^2)) = e + O(1/n),
Given the n = 3^2^85, i we take the log(10,n) = 2^85 log(10,3) ~ 1.85 *10^25, we get an estimate
similar to the quoted one
Repeatedly taking logs is a nice (usually) generally-applicable solution to problems of this sort. Here's a more special-case approach to this problem: recall that e = lim(n->infinity, (1+1/n)^n). So to be a good approximation to e, all we need is for 9^(4^(42)) (the denominator of the fractional part) to be sufficiently close to 3^(2^85) and big.
In this case, they're identical, so we have n=3^(2^85), and it's going to be a very good approximation to e. These are big numbers, but not unworkably so:
>>> from mpmath import *
>>> iv.dps = 50 # let's use interval arithmetic, just for fun
>>> x = mpi(9)**(-(4**(42)))
>>> up = (mpi(3)**(2**85))
>>> x
mpi('1.4846305545498656772753385085652043615636250118238876e-18457734525360901453873570',
'1.4846305545498656772753385085652043615636250118238899e-18457734525360901453873570')
>>> 1/x
mpi('6.7356824695231749871315222528985858700759934154677854e+18457734525360901453873569',
'6.7356824695231749871315222528985858700759934154678156e+18457734525360901453873569')
>>> up
mpi('6.7356824695231749871315222528985858700759934154678005e+18457734525360901453873569',
'6.7356824695231749871315222528985858700759934154678156e+18457734525360901453873569')
>>> 0 in (1/x-up)
True
Working out the exact error bounds on e is left as an exercise for the reader ;-) -- hint: compare the number of digits of accuracy the mathworld page claims and the above numbers, and ask why that might be, thinking of the series of approximations (1+1/1)^1, (1+1/2)^2, etc.

Resources