Buggy behavior of recur with primitives

39 views
Skip to first unread message

Handkea fumosa

unread,
Jun 28, 2009, 1:53:42 AM6/28/09
to Clojure
(defn foo [z-r z-i c-r c-i bailout max-iters]
(let [G__12819 (double c-r)
G__12820 (double c-i)
G__12817 (double -1)
G__12818 (double 2)
mi (int max-iters)
b (double (* bailout bailout))]
(loop [G__12815 (double z-r)
G__12816 (double z-i)
i (int 0)]
(if (> i mi)
:iters
(if (> (+ (* G__12815 G__12815) (* G__12816 G__12816)) b)
i
(recur
(+ (* G__12815 G__12815) (* G__12817 G__12816 G__12816)
G__12819)
(+ (* G__12818 G__12815 G__12816) G__12820)
(unchecked-inc i)))))))

#<CompilerException java.lang.RuntimeException:
java.lang.IllegalArgumentException: recur arg for primitive local:
G__12815 must be matching primitive (foo.clj:391)>

The recur arg in question is (+ (* G__12815 G__12815) (* G__12817
G__12816 G__12816) G__12819) all of whose operands are doubles.

This seems buggy.

(If you're asking why the meaningless names, it's because this is
actually adapted from the output of macroexpand-1. I have a macro to
turn symbolic mathematical expressions into optimized iteration loops.
It's not ready for prime-time yet; besides this problem, it doesn't do
common subexpression elimination, so for instance there's two of (*
G__12815 G__12815) in there.

But: this is the slightly-massaged output of (make-complex-double-
iteration-loop (:= z (+ c (** z 2)))) and close inspection will reveal
that it actually is a loop to iterate that, as a function of complex
numbers, until the modulus exceeds one limit or the iteration count
exceeds another limit. That I have a macro turning (:= z (+ c (** z
2))) into the above code is, I think, a significant accomplishment in
the area of math DSLs. And I did it in under five hours.)

Meikel Brandmeyer

unread,
Jun 28, 2009, 2:47:29 AM6/28/09
to clo...@googlegroups.com
Hi,

Am 28.06.2009 um 07:53 schrieb Handkea fumosa:

> The recur arg in question is (+ (* G__12815 G__12815) (* G__12817
> G__12816 G__12816) G__12819) all of whose operands are doubles.
>
> This seems buggy.

Yes, that seems ominous. I'm not doing much
number crunching (read: I don't need tight loops
with primitives), so I can't really tell, why it
doesn't work.

> (If you're asking why the meaningless names, it's because this is
> actually adapted from the output of macroexpand-1. I have a macro to
> turn symbolic mathematical expressions into optimized iteration loops.
> It's not ready for prime-time yet; besides this problem, it doesn't do
> common subexpression elimination, so for instance there's two of (*
> G__12815 G__12815) in there.

I don't know, how your macro looks like, but maybe
you can use the # notation: c-r# will give you something
like c-r__123.

However there are limitations for # notation (needs to be
in the same `). In that case you can specify a prefix to
gensym. (gensym "c-r__") will also give you c-r__123.

This should help making things in macros clearer.

Sincerely
Meikel

Jarkko Oranen

unread,
Jun 28, 2009, 8:35:21 AM6/28/09
to Clojure
<snip>

This is just a hunch, but maybe it's because you have three operands
on +? it's inlined only for two operands,
and uses reduce for more. Thus, your arguments might be getting boxed.

Try explicitly calling + (and *) with only two arguments at a time.

--
Jarkko

Rich Hickey

unread,
Jun 28, 2009, 11:29:43 AM6/28/09
to clo...@googlegroups.com

Yes, that is it. Alternatives for inlining other than binary ops are
under consideration.

Rich

Handkea fumosa

unread,
Jun 28, 2009, 11:43:51 AM6/28/09
to Clojure
On Jun 28, 2:47 am, Meikel Brandmeyer <m...@kotka.de> wrote:
> Hi,
>
> Am 28.06.2009 um 07:53 schrieb Handkea fumosa:
>
> > The recur arg in question is  (+ (* G__12815 G__12815) (* G__12817
> > G__12816 G__12816) G__12819) all of whose operands are doubles.
>
> > This seems buggy.
>
> Yes, that seems ominous. I'm not doing much
> number crunching (read: I don't need tight loops
> with primitives), so I can't really tell, why it
> doesn't work.
>
> > (If you're asking why the meaningless names, it's because this is
> > actually adapted from the output of macroexpand-1. I have a macro to
> > turn symbolic mathematical expressions into optimized iteration loops.
> > It's not ready for prime-time yet; besides this problem, it doesn't do
> > common subexpression elimination, so for instance there's two of (*
> > G__12815 G__12815) in there.
>
> I don't know, how your macro looks like, but maybe
> you can use the # notation: c-r# will give you something
> like c-r__123.

It's generating pretty much all of the code by list processing of
various kinds. I don't have

`(loop [foo ~bar baz ~quux] ~@body)

type stuff, I have stuff like

`(loop ~(vec (interleave (repeatedly #(gensym)) initial-values))
~@body)

:)

Reply all
Reply to author
Forward
0 new messages