# Re: Floating Point numbers vs Fixpoint numbers

I would like to thank all that helped with questions. My apologies for the very, very, very long message below. I tried to detail my recent experiences.

I have spent a fair amount of the last 4 days playing with PicoLisp. I thought I would give it a try even though it is quite primitive feeling to a person who is used to the richness of a Smalltalk. But it brings its own benefits. Small, efficient, the ability to understand the language and implementation. It seems for now that I am not at a level to use PicoLisp well. And I don't have the time to reach that point at the moment. But I don't like just appearing and disappearing without giving the wonderful people here the benefit of learning from my experience. Unfortunately it will be based on probably unreproducible experiences. Hopefully this will help someone.

The app I was exploring does a lot of floating point math. Simple calculations, but lots of them and repetitively. The fixpoint system of PicoLisp has been quite painful unfortunately.

I have a micro-benchmark that I wrote to test languages to see how they compare. And yes, I understand micro-benchmarks do not tell all about a language. But this does represent reasonably the domain I am exploring. I have explored with this benchmark C/C++, Java, Kotlin, Lua, LuaJit, Python, Python with Numpy, Nim, Pharo (Smalltalk), Dart all on my reasonably fast i7 laptop. They range in performance from about 2.4 minutes to over 6 hours to perform.

I ported this to PicoLisp and have experienced much pain. The port was not straightforward. And I have yet to get it to work. The benchmark is written in a way which all language should give the exact same results at the end of the test.

One of my big problems is that PicoLisp has continually segfaulted on me for unknown reasons. Something as simple as this has segfaulted.

jimmie@squirrel:~/Dev/languagetest\$ pil +
: (version)
17.5.16
-> (17 5 16)
: (scl 12)
-> 12
: (*Scl)
Segmentation fault (core dumped)

I will readily admit that when operating on my ported code that it could be my fault. I readily admit my code at any of the stages of its development could be broken and cause segfaults. However, when I broke it down in to smaller and smaller pieces in order to test out each piece, I have the above type problem of segfaults.

I will admit that I am out of my element when developing with a file based language. I do not know how to use debuggers or learn how to examine a core dump. Pharo delivers a live experience. Segfaults are rare and considered to be bad and should never happen. When they do it is attempt to reproduce them to fix either the vm or image. User coding errors should never cause a crash in Pharo. They is its model and the common one of Smalltalks. I am not trying to say that PicoLisp should be the same. Just explaining my experience.

I had trouble getting my code to run. When I did, it did not give the same results as any of the other implementations. So I began to reformat so that I could explore to find the problem and fix. I figure it has to do with the fixpoint verse floating point.

Dealing with fixpoint some conclusions.

Set *Scl as soon as possible.
Set *Scl for the smallest precision that will satisfy your requirements.
*Scl size has significant impact on performance and memory.

As frequently as possible, every calculation that sets a variable if possible. Have your function restore everything to the desired *Scl precision. Failure to do so affects performance and memory.

Natural integers and fixpoint do not play well with each other. In my benchmark I have loops which I use the index of the loop in the calculations. I had to insure that I did (* index 1.0) every time. Anytime I encounter a natural integer from some source, this needs to be done. If not, you will not get the proper results. This is stated in the documentation. But it does require additional effort to insure that every outside source of data which might provide an integer will have to be sanitized to work. This is something that feels unnatural in a dynamically typed language.

I guess at some point you would become accustomed to insuring that you do all of the above. But it just opens the door for simple mistakes or oversights when dealing with integers, fixpoint, floating point.

However the segfault problem is really stopping me from even attempting to overcome these issues. Below I have my code as it currently stands. My apologies if it is really ugly. I haven't yet learned Lisp. I have run the code for 1 rep sometimes successfully. The original test runs for 100 reps. It has never done so. It segfaults every time at 3 and above. Memory has been a constant 3.6mb ram. It doesn't grow and run out of memory. It just dies. :(

Below is with one rep.

jimmie@squirrel:~/Dev/languagetest\$ pil picoLisp-9.l +
: (doit)
"*Scl: " 12
"createlist"
"loop1"
25.360 sec
"loop2"
"nsum: " "11242.949400372845"
"navg: " "0.390380187512"
25.126 sec
51.657 sec
"nsum: " "11226.617500709850"
"navg: " "0.389813107663"
-> "0.389813107663"
: (bye)

Attempting the full 100.

jimmie@squirrel:~/Dev/languagetest\$ pil picoLisp-9.l +
: (doit)
"*Scl: " 12
"createlist"
"loop1"
Segmentation fault (core dumped)

At the first rate it would take about 1 1/2 hours to complete. If *Scl 12 would give the correct results. But it doesn't complete so I don't know. Comparing 1 rep doesn't match at the moment. But I am tired of segfaults and am giving up. I don't have the time for further exploration for a road I don't think I will pursue. I have experienced probably 40-50 segfaults over the last 2 days. It is inconsistent. Sometimes it will run, and sometimes not. It has not been a reproducible experience.

I am not blaming anybody or anything and fully understand I can be responsible for all of my problems. I also know that PicoLisp could be at a place that is beyond my current capabilities. I just wanted to provide my experience hoping someone might benefit.

Thanks for everything.

A successful 100 rep run should give an
nsum: 11322.307098752284    and
navg: 0.393135663151121    within acceptable floating point differences.

Here is the code. It could be broken, buggy and ugly.

(scl 12)

(de average (l)
(/ (sum + l) (length l)))

(de normalize (n)
(if (= n 0.0)
(setq nn 0.000123456789)
(setq nn n))
(while (<= nn 0.0001)
(setq nn (*/ nn 10.0 1.0)))
(while (>= nn 1.0)
(setq nn (*/ nn 0.1 1.0)))
nn)

(de createlist (lsize)
(setq l (range 1 lsize))
(for I (length l)
(set (nth l I) (normalize (* (nth l I 1) 1.0))))
l)

(de loop1calc (i j n)
(setq v
(*/ n
(+ (* i 1.0) n)
(- (* j 1.0) n)
0.1234567
(* 1.0 1.0 1.0)))
(normalize (*/ v v v (* 1.0 1.0))))

(de loop2calc (i j n)
(normalize
(*/ n
(+ (* j 1.0) 1.0)
(+ n n n)
0.1234567
(* 1.0 1.0 1.0))))

(de loop1 (l reps)
(for I reps
(for J (length l)
(setq n (nth l J 1))
(set (nth l J) (loop1calc I J n))
(setq nsum (sum + l))
(setq navg (average l)))))

(de loop2 (l reps)
(for I reps
(for J (length l)
(setq n (nth l J 1))
(set (nth l J) (loop2calc I J n))
(setq nsum (sum + l))
(setq navg (average l)))))

(de doit ()
(println "*Scl: " *Scl)
(bench
(setq reps 100)
(setq n 1.0)
(setq nsum 0.0)
(setq navg 0.0)
(println "createlist")
(setq l (createlist (* 60 24 5 4)))
(println "loop1")
(bench (loop1 l reps))
(println "loop2")
(println "nsum: " (format nsum *Scl))
(println "navg: " (format navg *Scl))
(bench (loop2 l reps)))
(println "nsum: " (format nsum *Scl))
(println "navg: " (format navg *Scl)))

On 07/13/2017 12:25 AM, Alexander Burger wrote:
Hi Jimmie,

What I didn't see in any of the examples is this

: (format (*/ 9.9 9.789 9.56789 `(* 1.0 1.0)) *Scl)
-> "927.23474457900000000000"
Good idea! I added this example to the reference of '*/'

♪♫ Alex

--
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe