# Plot library very slow with sqrt

**URL:** <https://racket.discourse.group/t/plot-library-very-slow-with-sqrt/2330>\
**Category:** Questions & Answers\
**Tags:** plot\
**Created:** [September 21, 2023, 12:45pm UTC](https://racket.discourse.group/t/plot-library-very-slow-with-sqrt/2330 "2023-09-21T12:45:02Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![matteo-daddio](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/matteo-daddio/32/1245_2.png) [@matteo-daddio](https://racket.discourse.group/u/matteo-daddio)\
**Post date:** [September 21, 2023, 12:45pm UTC](https://racket.discourse.group/t/plot-library-very-slow-with-sqrt/2330/1 "2023-09-21T12:45:02Z")

</div>

Hello,  
I'm working with the Plot library and I have a problem.  
When I try to plot, for example, the square root, this  
function i really fast:

```
(time (plot (function sqrt (- 0) 20)))
> cpu time: 359 real time: 358 gc time: 62

```

but this is really slow:

```
(time (plot (function sqrt (- 20) 20)))
> cpu time: 16750 real time: 16912 gc time: 406

```

This i really annoying. Is there a solution?

Matteo

---

<div class="post-metadata">

**Author:** ![Laurent.O](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/laurent.o/32/18_2.png) [@Laurent.O](https://racket.discourse.group/u/Laurent.O)\
**Post date:** [September 21, 2023, 12:55pm UTC](https://racket.discourse.group/t/plot-library-very-slow-with-sqrt/2330/2 "2023-09-21T12:55:21Z")

</div>

It's because on [-20, 0), `sqrt` produces imaginary numbers (try it in the repl), and plot filters them out, which apparently is pretty costly. This happens with other functions such as `log`, or functions that produce `+nan.0` on a large portion of the x-axis. I'm not too sure why though.

---

<div class="post-metadata">

**Author:** ![samth](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/samth/32/3_2.png) [@samth](https://racket.discourse.group/u/samth)\
**Post date:** [September 21, 2023, 4:05pm UTC](https://racket.discourse.group/t/plot-library-very-slow-with-sqrt/2330/3 "2023-09-21T16:05:00Z")

</div>

What's happening is that

1. `plot` uses Typed Racket and specifies a type for the argument to `function` that it takes `Real` to `Real`.
2. The type is translated to a contract when you use it in untyped Racket.
3. When plot passes inputs like `-10` to `sqrt` that fails the contract, triggering a contract error, which involves some expensive computation to print out the error message (something about packages).
4. plot then catches the exception to just not show that point on the graph, and tries other values.
5. Since this happens for a lot of negative values, the expensive error-formatting computation happens a lot of times, resulting in the slow program you see.

The most obvious optimization is for the contract error printing to not be so slow (why does it need to call `path->pkg+subpath` every time?) but maybe there's a way for `plot` to be smarter too.

---

<div class="post-metadata">

**Author:** ![robby](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/robby/32/7_2.png) [@robby](https://racket.discourse.group/u/robby)\
**Post date:** [September 21, 2023, 4:44pm UTC](https://racket.discourse.group/t/plot-library-very-slow-with-sqrt/2330/4 "2023-09-21T16:44:28Z")

</div>

Maybe a good idea is for plot change its type to `Number -> Number` and then to silently discard non-reals but to stop catching the exceptions (or just catch the first one and make sure that one gets displayed somehow in a useful way). Not that I'm a super heavy user of plot but it seems like I'd want to know if I passed a function in that was doing `(car #f)` or something like that, instead of returning a number. (Of course, this ship may have sailed for backwards compatibility reasons so maybe this has to be optional behavior.)

---

<div class="post-metadata">

**Author:** ![matteo-daddio](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/matteo-daddio/32/1245_2.png) [@matteo-daddio](https://racket.discourse.group/u/matteo-daddio)\
**Post date:** [September 21, 2023, 4:46pm UTC](https://racket.discourse.group/t/plot-library-very-slow-with-sqrt/2330/5 "2023-09-21T16:46:09Z")

</div>

The easiest workaround I’ve found is

```
(plot (function (lambda (x) (sqrt (abs x))) (- 20) 20))

```

A better solution is

```
(plot (function (lambda (x) (real-part (sqrt x))) (- 20) 20))

```

It’s also interesting to write

```
(plot (function (lambda (x) (imag-part (sqrt x))) (- 20) 20))

```

Matteo

---

<div class="post-metadata">

**Author:** ![Laurent.O](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/laurent.o/32/18_2.png) [@Laurent.O](https://racket.discourse.group/u/Laurent.O)\
**Post date:** [September 21, 2023, 6:10pm UTC](https://racket.discourse.group/t/plot-library-very-slow-with-sqrt/2330/6 "2023-09-21T18:10:04Z")

</div>

Just thinking aloud:  
How about delaying the evaluation of the exception message until it is actually used?  
Maybe using a parameter defaulting to immediate evaluation, and otherwise the exn message is a thunk that needs to be applied to obtain the actual string.

---

<div class="post-metadata">

**Author:** ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)\
**Post date:** [September 21, 2023, 6:40pm UTC](https://racket.discourse.group/t/plot-library-very-slow-with-sqrt/2330/7 "2023-09-21T18:40:04Z")

</div>

Is it faster to plot `real-sqrt` than `sqrt`?

```scheme
(define (real-sqrt x)
  (if (and (real? x) (not (negative? x))
       (sqrt (* 1.0 x)
       #f))

```

---

<div class="post-metadata">

**Author:** ![alexh](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/alexh/32/315_2.png) [@alexh](https://racket.discourse.group/u/alexh)\
**Post date:** [September 21, 2023, 10:51pm UTC](https://racket.discourse.group/t/plot-library-very-slow-with-sqrt/2330/8 "2023-09-21T22:51:32Z")

</div>

> [@matteo-daddio](#):
>
> The easiest workaround I’ve found is
> 
> ```scheme
> (plot (function (lambda (x) (sqrt (abs x))) (- 20) 20))
> 
> ```
> 
> A better solution is
> 
> ```scheme
> (plot (function (lambda (x) (real-part (sqrt x))) (- 20) 20))
> 
> ```
> 
> It’s also interesting to write
> 
> ```scheme
> (plot (function (lambda (x) (imag-part (sqrt x))) (- 20) 20))
> 
> ```
> 
> Matteo

A more interesting visualization is to use a `parametric` plot:

```scheme
#lang racket
(require plot)

(parameterize ([line-samples 5000]
               [line-width 3])
  (plot
   (parametric
    (lambda (t)
      (let ([s (sqrt t)])
        (vector (real-part s) (imag-part s)))) -20 20 #:label "sqrt(t)")
   #:x-min -4 #:x-max 4 #:y-min -4 #:y-max 4
   #:x-label "Real Axis" #:y-label "Imaginary Axis"))

```

Produces:

![sqrt-plot](https://global.discourse-cdn.com/free1/uploads/racket/original/2X/f/fec329b70ca1282e8053ea2284c7e55fcb07fa81.png)
