How to change Racket expression to Float type following Optimization Coach suggestion? - optimization

I am writing a small numeric program, using Typed Racket. I want to improve its performance, and installed the Optimization Coach plugin in DrRacket. However, I am not able to follow its advice in the very first suggestion that it outputs.
The code is the following (you can see it in context here in Github):
(define: 𝛆 : Positive-Integer 20)
(define: base : Positive-Integer 10)
(define: N : Integer (* (+ n 𝛆) (exact-floor (/ (log base) (log 2)))))
and the Optimization Coach output is the following:
This seems simple enough, right? 2 can be changed to 2.0 and this yields an optimization (a less red color on the line), but it is base that I cannot touch without getting a TypeCheck error.
Defining or casting base as Float
(define: base : Float 10.0)
;; or
(log (cast base Float))
leads to:
❯ raco exe bellard.rkt
bellard.rkt:31:47: Type Checker: type mismatch
expected: Real
given: Number
in: (/ (log base) (log 2))
How can I perform this optimization? Any help is appreciated.

This is a bit silly, but I found the answer to my question in the paper that presents Optimization Coach, which I had read too hastily.
Unbeknownst to the programmer, however, this code suffers
from a special case in Racket’s treatment of mixed-type
arithmetic. Integer-float multiplication produces a floating
point number, unless the integer is 0, in which case the result
is the integer 0. Thus the result of the above multiplication
is a floating-point number most of the time, but not always,
making floating-point specialization unsafe
I supposed this also applied to mixed-type division, and changed my code to:
(define: N : Integer (* (+ n 𝛆) (exact-floor (/ (log (exact->inexact base))
(log 2.0)))))
The optimization is confirmed by the plugin with a green line.

Related

Kotlin: Why these two implementations of log base 10 give different results on the specific imputs?

println(log(it.toDouble(), 10.0).toInt()+1) // n1
println(log10(it.toDouble()).toInt() + 1) // n2
I had to count the "length" of the number in n-base for non-related to the question needs and stumbled upon a bug (or rather unexpected behavior) that for it == 1000 these two functions give different results.
n1(1000) = 3,
n2(1000) = 4.
Checking values before conversion to int resulted in:
n1_double(1000) = 3.9999999999999996,
n2_double(1000) = 4.0
I understand that some floating point arithmetics magic is involved, but what is especially weird to me is that for 100, 10000 and other inputs that I checked n1 == n2.
What is special about it == 1000? How I ensure that log gives me the intended result (4, not 3.99..), because right now I can't even figure out what cases I need to double-check, since it is not just powers of 10, it is 1000 (and probably some other numbers) specifically.
I looked into implementation of log() and log10() and log is implemented as
if (base <= 0.0 || base == 1.0) return Double.NaN
return nativeMath.log(x) / nativeMath.log(base) //log() here is a natural logarithm
while log10 is implemented as
return nativeMath.log10(x)
I suspect this division in the first case is the reason of an error, but I can't figure out why it causes an error only in specific cases.
I also found this question:
Python math.log and math.log10 giving different results
But I already know that one is more precise than another. However there is no analogy for log10 for some base n, so I'm curious of reason WHY it is specifically 1000 that goes wrong.
PS: I understand there are methods of calculating length of a number without fp arithmetics and log of n-base, but at this point it is a scientific curiosity.
but I can't figure out why it causes an error only in specific cases.
return nativeMath.log(x) / nativeMath.log(base)
//log() here is a natural logarithm
Consider x = 1000 and nativeMath.log(x). The natural logarithm is not exactly representable. It is near
6.90775527898213_681... (Double answer)
6.90775527898213_705... (closer answer)
Consider base = 10 and nativeMath.log(base). The natural logarithm is not exactly representable. It is near
2.302585092994045_901... (Double)
2.302585092994045_684... (closer answer)
The only exactly correct nativeMath.log(x) for a finite x is when x == 1.0.
The quotient of the division of 6.90775527898213681... / 2.302585092994045901... is not exactly representable. It is near 2.9999999999999995559...
The conversion of the quotient to text is not exact.
So we have 4 computation errors with the system giving us a close (rounded) result instead at each step.
Sometimes these rounding errors cancel out in a way we find acceptable and the value of "3.0" is reported. Sometimes not.
Performed with higher precision math, it is easy to see log(1000) was less than a higher precision answer and that log(10) was more. These 2 round-off errors in the opposite direction for a / contributed to the quotient being extra off (low) - by 1 ULP than hoped.
When log(x, 10) is computed for other x = power-of-10, and the log(x) is slightly more than than a higher precision answer, I'd expect the quotient to less often result in a 1 ULP error. Perhaps it will be 50/50 for all powers-of-10.
log10(x) is designed to compute the logarithm in a different fashion, exploiting that the base is 10.0 and certainly exact for powers-of-10.

Avoiding float to pointer coercion in Common Lisp

I use SBCL (64-bit v1.4.0) for numerical calculation.
After enabling optimization, following compiler note appears:
note: doing float to pointer coercion (cost 13) to "<return value>"
The code I use is as follows:
(defun add (a b)
(declare (optimize (speed 3) (safety 0)))
(declare (double-float a b))
(the double-float (+ a b)))
I've also tried ftype and got the same note.
On the other hand, following code doesn't show the note:
(defun add-fixnum (a b)
(declare (optimize (speed 3) (safety 0)))
(declare (fixnum a b))
(the fixnum (+ a b)))
I think double-float and fixnum are both 64 bits wide.
Why can not SBCL return a double-float value via a register like C language? And are there any way to avoid float to pointer coercion without inline expansion?
The problem is that Lisp data is dynamically typed, and the return value of a function has to include the type information. The type tag in most implementations is stored in the low-order bits of a value.
This allows a special optimization for fixnums. Their type tag is all zeroes, and the value is the integer shifted left by the number of bits in the type tag. When you add these values, the result still has zeroes in the tag bits, so you can perform arithmetic on the values using normal CPU operations.
But this doesn't work for floating point values. After performing the CPU operations, it has to add the type tag to the value. This is what it means by "float to pointer coercion" (a more common word for it in many languages is "boxing").
Declaring the return type doesn't avoid this, because the callers don't necessarily have access to the declarations -- Lisp allows you to compile the callers in a separate compilation unit than the functions they call.
If you declare the function INLINE, then this doesn't need to be done, because the callers know the type it's returning, and the hardware value can be returned directly to them without adding the tag.
A more detailed explanation can be found in this ancient comp.lang.lisp thread. It's referring to CMUCL, which is what SBCL is derived from (notice that the wording of the warning is exactly the same).

How to multiply integer with float values in Smalltalk

I am learning Smalltalk a few days ago and, I am working on the project that is basically finding the Area and Perimeter for Circle Class that is implementing from Shape Class. In other words, Shape is a super class for Circle.
When I run my code, I got the error saying, "numeric primitive expected numeric argument, got ". I believe that the error occurs because I am multiplying integer with float value. I have no idea how to fix the error, so if someone can please give me some suggestions?
P.S - I am using usmalltalk, which is a specific version of Smalltalk, but it has the same features.
(class Shape Object
(Perimeter Area)
(method getPerimeter() Perimeter)
(method setPerimeter:(Perim)
(set Perimeter Perim)
)
(method CreateShape::(Perim Ar)
(set Perimeter Perim)
(set Area Ar)
self
)
(class-method NewShape:: (Perimeter Area)
(CreateShape:: (new self) Perimeter Area)
)
)
(class Circle Shape
(Radius)
(method getRadius() Radius)
(method setRadius:(radi)
(set Radius radi)
(set Perimeter (* (* 2 (asFloat (/ 22 7))) Radius)) #The error exits here
(set Area (* (* (asFloat (/ 22 7)) Radius) Radius))
)
(method CreateCircle:(radi)
(set Radius radi)
self
)
(class-method NewCircle: (Radius)
(CreateCircle: (new self) Radius)
)
)
The Smalltalk dialect you are using doesn't follow the conventional Smalltalk syntax, so let me translate the offending expression into the more familiar one.
Let's parse the expression
(* (* 2 (asFloat (/ 22 7))) Radius)
In what follows, the expression on the right of --> is the conventional form of the expression on the left.
Step 1:
/ 22 27 --> 22/27
Step 2:
asFloat(/ 22 7) --> (22/27) asFloat
Step 3:
* 2 (asFloat (/ 22 27)) --> 2 * (22/27) asFloat
Step 4:
* (* 2 (asFloat (/ 22 27)) Radius) --> (2 * (22 / 27) asFloat) * Radius
Therefore, an error here means that Radius is not a number. As suggested in the comments, the problem is that the Radius variable has not been assigned a proper (i.e., numeric) value, and this is what the error message is somehow trying to tell.
Of course, the Radius variable takes its value from the radi argument sent to the setRadius: method. This means that the origin of the problem is in the sender of setRadius:. But here is where the analysis of the source code gets tricky because it is static and it doesn't show the sequence of steps in the execution of your program.
A better approach to understand the problem is a dynamic one. In Smalltalk you do that with the help of the debugger. I'm not familiar with the Smalltalk dialect you are using, but when the error pops up, you should be offered some way to debug your code. Accept that option and examine the list of messages that were sent right before the error was signaled. Once you locate the method that evaluates the expression at Step 4, check the value of the Radius variable and see what's in there. It shouldn't be a number, otherwise there wouldn't be any error. From there you should be able to trace back to the place where the formal argument radi gets its actual value, which leads to the root of the problem.
One final remark. Your question reads How to multiply integers with floats in Smalltalk. The answer is just multiply them using *. Smalltalk will figure it out how to proceed. You don't need to send any conversion messages such as asFloat or the like (you can remove them from your code so to simplify it.) Smalltalk dynamic typing frees the programmer from spending time in type-casting variables. Not because there is any magic in the compiler but because of the polymorphic nature of the language.

Is this syntax good form: "PI / (double) (i - j)" in C?

EDIT β€” Actually the syntax was not good form, because there is a superlative statement, which is a fair reason for me being confused, whether it is good form, and if so, why. It's my first C code ever, grafting 9 research journal algorithms inside 1000 line code from 1989.
What is a double-type in between brackets:
PI / (double) (i - j);
Is it to ensure that the result is a float?
The bigger expression statement is:
xi[i] = xi[i] + 2.0 * xr[j] / PI / (double) (i - j);
There's nothing "antiquated" about it, it's a normal C type cast.
Assuming PI is of a floating-point type, which seems safe, the division will be performed using the type of PI thanks to promotion.
So, the cast might (depending on the context) have value if PI is of type float, but you really want the division to happen at double precision. Of course, it would make more sense to actually cast PI in that case ...

How can I prove that derivations in Chomsky Normal Form require 2n - 1 steps?

I'm trying to prove the following:
If G is a Context Free Grammar in the Chomsky Normal Form, then for any string w belongs L(G) of length n β‰₯ 1, it requires exactly 2n-1 steps to make any derivation of w.
How would I go about proving this?
As a hint - since every production in Chomsky Normal Form either has the form
S β†’ AB, for nonterminals A and B, or the form
S β†’ x, for terminal x,
Then deriving a string would work in the following way:
Create a string of exactly n nonterminals, then
Expand each nonterminal out to a single terminal.
Applying productions of the first form will increase the number of nonterminals from k to k + 1, since you replace one nonterminal (-1) with two nonterminals (+2) for a net gain of +1 nonterminal. Since your start with one nonterminal, this means you need to do n - 1 productions of the first form. You then need n more of the second form to convert the nonterminals to terminals, giving a total of n + (n - 1) = 2n - 1 productions.
To show that you need exactly this many, I would suggest doing a proof by contradiction and showing that you can't do it with any more or any fewer. As a hint, try counting the number of productions of each type that are made and showing that if it isn't 2n - 1, either the string is too short, or you will still have nonterminals remaining.
Hope this helps!