<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hi Steve<div class="">I didn’t implement exact arithmetic with foreign functions, but I tried.<div class=""><div class="">I spoke with a numerical specialist; they had fast GCD code, but only up to some fixed extended number range, based on a fixed longer representation.</div><div class="">They couldn’t believe that I would ever need more rational precision than that, but suggested that I could put together a C library that overflows to Lisp.</div><div class="">I did some random observations of numbers in my app; I saw many samples in the Lisp-only bignum range.</div><div class="">QED I stayed on the Lisp track.</div><div class="">Martin</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><div><blockquote type="cite" class=""><div class="">On Jun 19, 2020, at 8:55 PM, Steven Nunez <<a href="mailto:steve_nunez@yahoo.com" class="">steve_nunez@yahoo.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><div class="ydp675aaf1eyahoo-style-wrap" style="font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:13px;"><div class=""></div>
        <div dir="ltr" data-setdir="false" class="">Martin, did you do any benchmarks on the difference between, say, CFFI and using the internal code as a template?<br class=""></div><div class=""><br class=""></div>
        
        </div><div id="yahoo_quoted_3120179272" class="yahoo_quoted">
            <div style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;color:#26282a;" class="">
                
                <div class="">
                    On Friday, June 19, 2020, 8:32:22 AM GMT+8, martin <<a href="mailto:brooks.martin@sympatico.ca" class="">brooks.martin@sympatico.ca</a>> wrote:
                </div>
                <div class=""><br class=""></div>
                <div class=""><br class=""></div>
                <div class=""><div id="yiv4860178186" class=""><div class="">Hello CCL fans, I will relate a somewhat parallel story.<div class="yiv4860178186">My application requires exact arithmetic, i.e. bignum rationals.</div><div class="yiv4860178186">CCL 11 conses like crazy for bignum rationals, whereas CCL 12 has a specialized implementation.</div><div class="yiv4860178186">This happened because I engaged Clozure Associates to solve my bignum rational problem, which they totally did.</div><div class="yiv4860178186">Prior to engaging CA I raided the CCL code to use the low-level allocation and arithmetic %functions, as in the examples below.</div><div class="yiv4860178186"><br class="yiv4860178186" clear="none"></div><div class="yiv4860178186">Martin</div><div class="yiv4860178186"><br class="yiv4860178186" clear="none"></div><div class="yiv4860178186"><div class="yiv4860178186"><div class=""><br class="yiv4860178186" clear="none"><blockquote class="yiv4860178186" type="cite"><div class="yiv4860178186yqt9195486361" id="yiv4860178186yqt26868"><div class="yiv4860178186">On Jun 18, 2020, at 7:56 PM, Steven Nunez <<a rel="nofollow" shape="rect" class="yiv4860178186" ymailto="mailto:steve_nunez@yahoo.com" target="_blank" href="mailto:steve_nunez@yahoo.com">steve_nunez@yahoo.com</a>> wrote:</div><br class="yiv4860178186Apple-interchange-newline" clear="none"><div class="yiv4860178186"><div class="yiv4860178186"><div class="yiv4860178186ydpde0f8651yahoo-style-wrap" style="font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:13px;"><div class="yiv4860178186"></div>
        <div class="yiv4860178186" dir="ltr"><div class="yiv4860178186"><div class="yiv4860178186" dir="ltr">Yes, that's been my experience as well. Part of the 
reason for the question was to try to gain insights from anyone that 
might have done something similar and to understand why the code for CCL
 was written as it is. There's some reason why Gary B et. al. did things
 the way they did, and knowing that will help in my coding efforts.<br class="yiv4860178186" clear="none"></div><div class="yiv4860178186"><br class="yiv4860178186" clear="none"><br class="yiv4860178186" clear="none"></div></div><div class="yiv4860178186"><br class="yiv4860178186" clear="none"></div></div><div class="yiv4860178186"><br class="yiv4860178186" clear="none"></div>
        
        </div><div class="yiv4860178186yahoo_quoted" id="yiv4860178186yahoo_quoted_3041486737">
            <div class="yiv4860178186" style="font-family:'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;color:#26282a;">
                
                <div class="yiv4860178186">
                    On Friday, June 19, 2020, 5:01:20 AM GMT+8, Ron Garret <<a rel="nofollow" shape="rect" class="yiv4860178186" ymailto="mailto:ron@flownet.com" target="_blank" href="mailto:ron@flownet.com">ron@flownet.com</a>> wrote:
                </div>
                <div class="yiv4860178186"><br class="yiv4860178186" clear="none"></div>
                <div class="yiv4860178186"><br class="yiv4860178186" clear="none"></div>
                <div class="yiv4860178186"><div class="yiv4860178186" id="yiv4860178186"><div class="yiv4860178186">The best way to answer performance questions is just to run some benchmarks.<div class="yiv4860178186"><br class="yiv4860178186" clear="none"><div class="yiv4860178186"><div class="yiv4860178186yqt1136114722" id="yiv4860178186yqt44587"><div class="yiv4860178186">On Jun 18, 2020, at 1:58 AM, Steven Nunez <<a rel="nofollow" shape="rect" class="yiv4860178186" ymailto="mailto:steve_nunez@yahoo.com" target="_blank" href="mailto:steve_nunez@yahoo.com">steve_nunez@yahoo.com</a>> wrote:</div><br class="yiv4860178186Apple-interchange-newline" clear="none"><blockquote class="yiv4860178186" type="cite"><div class="yiv4860178186"><div class="yiv4860178186yahoo-style-wrap" style="font-family:Helvetica Neue, Helvetica, Arial, sans-serif;font-size:13px;"><div class="yiv4860178186" dir="ltr">Greetings all,</div><div class="yiv4860178186" dir="ltr"><br class="yiv4860178186" clear="none"></div><div class="yiv4860178186" dir="ltr">I've got need of a few functions that are in the standard C library, but not in common lisp. Since the functions are there, but not available, I set about wrapping them. Looking at the code for <font class="yiv4860178186" face="lucida console, sans-serif">atanh</font>, I was surprised that CCL's wrapping is so complicated. Now I get that the code, pasted below, has to cater for complex numbers, multiple architectures and the like, so I can likely simplify it for my use case in one architecture and the real domain.</div><div class="yiv4860178186" dir="ltr"><br class="yiv4860178186" clear="none"></div><div class="yiv4860178186" dir="ltr">So, my question is: is this best practice for getting good performance for a wrapper? In Allegro, where I don't have access to the code, things are much simpler, using their FFI, e.g.</div><div class="yiv4860178186" dir="ltr"><br class="yiv4860178186" clear="none"></div><div class="yiv4860178186" dir="ltr"><div class="yiv4860178186"><font class="yiv4860178186" face="lucida console, sans-serif">  (ff:def-foreign-call (%erf "erf") ((x :double))<br class="yiv4860178186" clear="none">    :returning :double)<br class="yiv4860178186" clear="none">  (ff:def-foreign-call (%erff "erff") ((x :float))<br class="yiv4860178186" clear="none">    :returning :float)<br class="yiv4860178186" clear="none">  (defun erf (x)<br class="yiv4860178186" clear="none">    "Returns the error function value for x"<br class="yiv4860178186" clear="none">    (cond ((typep x 'double-float) (%erf x))<br class="yiv4860178186" clear="none">      ((typep x 'single-float) (%erff x))))</font></div><div class="yiv4860178186"><br class="yiv4860178186" clear="none"></div></div><div class="yiv4860178186" dir="ltr"><br class="yiv4860178186" clear="none"></div><div class="yiv4860178186" dir="ltr">Whereas in the CCL code there's <font class="yiv4860178186" face="lucida console, sans-serif">%setf-double-float</font>, and <font class="yiv4860178186" face="lucida console, sans-serif">target::with-stack-double-floats</font>, all of which seem undocumented, but look like they're doing some magic to keep things fast and/or efficient. These functions are already in the database, so it's tempting to use the #_ macro to access them, but then I wonder why the CCL guys didn't do this.<br class="yiv4860178186" clear="none"></div><div class="yiv4860178186" dir="ltr"><br class="yiv4860178186" clear="none"></div><div class="yiv4860178186" dir="ltr">Anyone got any ideas here? I guess I'm wondering as well whether or not I'll get any performance benefit from following the CCL pattern over a simpler approach.<br class="yiv4860178186" clear="none"></div><div class="yiv4860178186" dir="ltr"><br class="yiv4860178186" clear="none"></div><div class="yiv4860178186" dir="ltr"><font class="yiv4860178186" face="lucida console, sans-serif"><br class="yiv4860178186" clear="none"></font></div><div class="yiv4860178186" dir="ltr"><div class="yiv4860178186"><font class="yiv4860178186" face="lucida console, sans-serif">#+windows-target<br class="yiv4860178186" clear="none">(progn<br class="yiv4860178186" clear="none">(defun %double-float-atanh! (n result)<br class="yiv4860178186" clear="none">  (declare (double-float n result))<br class="yiv4860178186" clear="none">  (with-stack-double-floats ((temp))<br class="yiv4860178186" clear="none">    (%setf-double-float TEMP (external-call "atanh" :double n :double))<br class="yiv4860178186" clear="none">    (%df-check-exception-1 'atanh n (%ffi-exception-status))<br class="yiv4860178186" clear="none">    (%setf-double-float result TEMP)))<br class="yiv4860178186" clear="none"><br class="yiv4860178186" clear="none">#+32-bit-target<br class="yiv4860178186" clear="none">(defun %single-float-atanh! (n result)<br class="yiv4860178186" clear="none">  (declare (single-float n result)) <br class="yiv4860178186" clear="none">  (target::with-stack-short-floats ((temp))<br class="yiv4860178186" clear="none">    #+arm-target (%set-fpscr-status 0)<br class="yiv4860178186" clear="none">    (%setf-short-float TEMP (external-call "atanhf" :float n :float))<br class="yiv4860178186" clear="none">    (%sf-check-exception-1 'atanh n (%ffi-exception-status))<br class="yiv4860178186" clear="none">    (%setf-short-float result TEMP)))<br class="yiv4860178186" clear="none"><br class="yiv4860178186" clear="none">#+64-bit-target<br class="yiv4860178186" clear="none">(defun %single-float-atanh (n)<br class="yiv4860178186" clear="none">  (declare (single-float n)) <br class="yiv4860178186" clear="none">  (let* ((result (external-call "atanhf" :float n :float)))<br class="yiv4860178186" clear="none">    (%sf-check-exception-1 'atanh n (%ffi-exception-status))<br class="yiv4860178186" clear="none"></font><div class="yiv4860178186"><font class="yiv4860178186" face="lucida console, sans-serif">    result))</font><font class="yiv4860178186" face="lucida console, sans-serif">)</font></div><div class="yiv4860178186"><font class="yiv4860178186" face="lucida console, sans-serif"><br class="yiv4860178186" clear="none"></font></div><div class="yiv4860178186" dir="ltr"><div class="yiv4860178186"><font class="yiv4860178186" face="lucida console, sans-serif">(defun atan (y &optional (x nil x-p))<br class="yiv4860178186" clear="none">  "Return the arc tangent of Y if X is omitted or Y/X if X is supplied."<br class="yiv4860178186" clear="none">  (cond (x-p<br class="yiv4860178186" clear="none">         (cond ((or (typep x 'double-float)<br class="yiv4860178186" clear="none">                    (typep y 'double-float))<br class="yiv4860178186" clear="none">                (with-stack-double-floats ((dy y)<br class="yiv4860178186" clear="none">                                           (dx x))<br class="yiv4860178186" clear="none">                  (%df-atan2 dy dx)))<br class="yiv4860178186" clear="none">               (t<br class="yiv4860178186" clear="none">                (when (and (rationalp x) (rationalp y))<br class="yiv4860178186" clear="none">                  ;; rescale arguments so that the maximum absolute value is 1<br class="yiv4860178186" clear="none">                  (let ((x1 (abs x)) (y1 (abs y)))<br class="yiv4860178186" clear="none">                    (cond ((> y1 x1)<br class="yiv4860178186" clear="none">                           (setf x (/ x y1))<br class="yiv4860178186" clear="none">                           (setf y (signum y)))<br class="yiv4860178186" clear="none">                          ((not (zerop x))<br class="yiv4860178186" clear="none">                           (setf y (/ y x1))<br class="yiv4860178186" clear="none">                           (setf x (signum x))))))<br class="yiv4860178186" clear="none">                #+32-bit-target<br class="yiv4860178186" clear="none">                (target::with-stack-short-floats ((sy y)<br class="yiv4860178186" clear="none">                                                  (sx x))<br class="yiv4860178186" clear="none">                  (%sf-atan2! sy sx))<br class="yiv4860178186" clear="none">                #+64-bit-target<br class="yiv4860178186" clear="none">                (%sf-atan2 (%short-float y) (%short-float x)))))<br class="yiv4860178186" clear="none">        ((typep y 'double-float)<br class="yiv4860178186" clear="none">         (%double-float-atan! y (%make-dfloat)))<br class="yiv4860178186" clear="none">        ((typep y 'single-float)<br class="yiv4860178186" clear="none">         #+32-bit-target<br class="yiv4860178186" clear="none">         (%single-float-atan! y (%make-sfloat))<br class="yiv4860178186" clear="none">         #+64-bit-target<br class="yiv4860178186" clear="none">         (%single-float-atan y))<br class="yiv4860178186" clear="none">        ((typep y 'rational)<br class="yiv4860178186" clear="none">         (cond ((<= (abs y) most-positive-short-float)<br class="yiv4860178186" clear="none">                #+32-bit-target<br class="yiv4860178186" clear="none">                (target::with-stack-short-floats ((sy y))<br class="yiv4860178186" clear="none">                  (%single-float-atan! sy (%make-sfloat)))<br class="yiv4860178186" clear="none">                #+64-bit-target<br class="yiv4860178186" clear="none">                (%single-float-atan (%short-float y)))<br class="yiv4860178186" clear="none">               ((minusp y)<br class="yiv4860178186" clear="none">                #.(- single-float-half-pi))<br class="yiv4860178186" clear="none">               (t<br class="yiv4860178186" clear="none">                single-float-half-pi)))<br class="yiv4860178186" clear="none">        (t<br class="yiv4860178186" clear="none">         (let ((r (realpart y))<br class="yiv4860178186" clear="none">               (i (imagpart y)))<br class="yiv4860178186" clear="none">           (if (zerop i)<br class="yiv4860178186" clear="none">             (complex (atan r) i)<br class="yiv4860178186" clear="none">             (i* (%complex-atanh (complex (- i) r)) -1))))))</font></div><div class="yiv4860178186"><br class="yiv4860178186" clear="none"></div></div></div><div class="yiv4860178186"><br class="yiv4860178186" clear="none"></div></div></div></div>_______________________________________________<br class="yiv4860178186" clear="none">Openmcl-devel mailing list<br class="yiv4860178186" clear="none"><a rel="nofollow" shape="rect" class="yiv4860178186" ymailto="mailto:Openmcl-devel@clozure.com" target="_blank" href="mailto:Openmcl-devel@clozure.com">Openmcl-devel@clozure.com</a><br class="yiv4860178186" clear="none"><a rel="nofollow" shape="rect" class="yiv4860178186" target="_blank" href="https://lists.clozure.com/mailman/listinfo/openmcl-devel">https://lists.clozure.com/mailman/listinfo/openmcl-devel</a><br class="yiv4860178186" clear="none"></blockquote></div></div><br class="yiv4860178186" clear="none"></div></div></div></div>
            </div>
        </div></div>_______________________________________________<br class="yiv4860178186" clear="none">Openmcl-devel mailing list<br class="yiv4860178186" clear="none"><a rel="nofollow" shape="rect" class="yiv4860178186" ymailto="mailto:Openmcl-devel@clozure.com" target="_blank" href="mailto:Openmcl-devel@clozure.com">Openmcl-devel@clozure.com</a><br class="yiv4860178186" clear="none"><a href="https://lists.clozure.com/mailman/listinfo/openmcl-devel" class="">https://lists.clozure.com/mailman/listinfo/openmcl-devel</a><br class="yiv4860178186" clear="none"></div></div></blockquote></div><br class="yiv4860178186" clear="none"></div></div></div></div></div>
            </div>
        </div></div></div></blockquote></div><br class=""></div></div></div></body></html>