From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Emanuel Berg Newsgroups: gmane.emacs.devel Subject: Re: Adding a generic mathematical library Date: Wed, 17 Jul 2024 00:06:49 +0200 Message-ID: <878qy1at52.fsf@dataswamp.org> References: <8734o9sdig.fsf@posteo.net> <87wmllqq66.fsf@posteo.net> <87plrdqnhc.fsf@posteo.net> <87le21qldj.fsf_-_@posteo.net> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="1788"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) To: emacs-devel@gnu.org Cancel-Lock: sha1:6wTCFKb0DV6KEtlA8CjKN/wSoRA= Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Wed Jul 17 04:32:55 2024 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1sTuTP-0000E7-B4 for ged-emacs-devel@m.gmane-mx.org; Wed, 17 Jul 2024 04:32:55 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sTuSd-0006YL-3R; Tue, 16 Jul 2024 22:32:07 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sTqK9-0005sP-0r for emacs-devel@gnu.org; Tue, 16 Jul 2024 18:07:05 -0400 Original-Received: from ciao.gmane.io ([116.202.254.214]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sTqK6-0000Sc-KV for emacs-devel@gnu.org; Tue, 16 Jul 2024 18:07:04 -0400 Original-Received: from list by ciao.gmane.io with local (Exim 4.92) (envelope-from ) id 1sTqK1-0002FK-Bb for emacs-devel@gnu.org; Wed, 17 Jul 2024 00:06:57 +0200 X-Injected-Via-Gmane: http://gmane.org/ Mail-Followup-To: emacs-devel@gnu.org Mail-Copies-To: never Received-SPF: pass client-ip=116.202.254.214; envelope-from=ged-emacs-devel@m.gmane-mx.org; helo=ciao.gmane.io X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Tue, 16 Jul 2024 22:32:01 -0400 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:321739 Archived-At: Philip Kaludercic wrote: >> Someoneā„¢ should propose a concrete suggestion. > > I've rename the thread to get some more attention, and also > wanted to mention, that if we do so, I think putting some > thought into the design wouldn't be bad. Including an > infix-notation macro and perhaps even overloaded operator > support ala APL would be a nice thing to have. We'd have to > weigh the cost of this kind of flexibility with performance, > unless someone were to write a specialised byte-compiler. Yeah, I've pushed for a math library for a long time. I have several files that are very close to that (for stats, time, permutations and so on) but I also have a math.el which I yank below if any of it can be used. I'd love to stay in the loop and read more on this! ;;; -*- lexical-binding: t -*- ;; ;; this file: ;; https://dataswamp.org/~incal/emacs-init/math.el (require 'cl-lib) (require 'dwim) ; https://dataswamp.org/~incal/emacs-init/dwim.el (require 'perm) ; https://dataswamp.org/~incal/emacs-init/perm.el (defun nand (&rest conditions) (when (member nil conditions) t) ) ;; (nand) ; nil ;; (nand 1 2 3) ; nil ;; (nand nil) ; t ;; (nand 1 2 nil 3) ; t ;; (not (and)) ; nil ;; (not (and 1 2 3)) ; nil ;; (not (and nil)) ; t ;; (not (and 1 2 nil 3)) ; t (defalias '** #'expt) (defalias 'ceil #'ceiling) (defun percent-change (from to) (if (= from to) 0 (/ (- to from) (abs from) 0.01))) ;; (percent-change 1 2) ; 100 ;; (percent-change 1 1) ; 0 ;; (percent-change 1 0) ; -100 ;; (percent-change 1 -1) ; -200 ;; ;; (percent-change 0 1) ; 1.0e+INF ;; (percent-change 0 0) ; 0 ;; (percent-change 0 -1) ; -1.0e+INF ;; ;; (percent-change -1 1) ; 200 ;; (percent-change -1 0) ; 100 ;; (percent-change -1 -1) ; 0 ;; (percent-change -1 -2) ; -100 (defun distance-point (min max) (+ min (/ (- max min) 2.0)) ) ;; (distance-point 1 5) ; 3 ;; (distance-point 1 10) ; 5.5 ;; (distance-point 60 100) ; 80 (defun // (nom denom) (/ nom denom 1.0) ) ;; (/ 8 256) ; 0 ;; (// 8 256) ; 0.03125 (defun arith-sum (n) (cl-loop with sum = 0 for i from 1 to (1- n) do (cl-incf sum i) finally return sum) ) (defun digs (n) (* n (1- n)) ) (defun mean-value (vs) (let*((sum (apply #'+ vs)) (mean (/ sum (length vs) 1.0)) ) mean) ) (defun mean-str (strs) (mean-value (cl-map 'list #'length strs)) ) (defun faster (old new) (format "%.1f%%" (* 100 (1- (/ new old 1.0)))) ) ;; (faster 0.2 0.5) ; 150.0% ;; (faster 1.35 0.84) ; -37.8% ;; (faster 200 400) ; 100.0% ;; (faster 1000 1000) ; 0.0% ;; (faster 1000 100) ; -90.0% (defun percent (nom &optional denom str) (or denom (setq denom 1)) (let ((perc (/ nom denom 0.01))) (if str (format "%.1f%%" perc) perc))) ;; (percent 0.25) ; 25.0 ;; (percent 50 75) ; 66.66 ... ;; (percent (// 1 2) nil t) ; 50.0% ;; (percent 1019 22 t) ; 4631.8% (let ((min-def 0) (max-def 9) (inc-def 1) ) (defun interval (&optional min max inc) (interactive `(,(read-number "min: " min-def) ,(read-number "max: " max-def) ,(read-number "inc: " inc-def)) ) (or min (setq min min-def)) (or max (setq max max-def)) (or inc (setq inc inc-def)) (unless (<= min max) (error "Bogus interval") ) (unless (> inc 0) (error "Bogus increment") ) (cl-loop for i from min to max by inc collect i) ) (declare-function interval nil) ) ;; (interval 10 5) ; Bogus interval ;; (interval 1 3 -1) ; Bogus increment ;; (interval 5 10) ; (5 6 7 8 9 10) ;; (interval 1.8 2.0 0.1) ; (1.8 1.9 2.0) ;; (interval) ; (0 1 2 3 4 5 6 7 8 9) ;; (interval 19 99) ; (19 20 21 ... 97 98 99) (defun digits-sum (&optional beg end) (interactive (use-region)) (or beg (setq beg (point-min))) (or end (setq end (point-max))) (let ((sum 0)) (goto-char beg) (while (re-search-forward " [[:digit:].]+ " end t) (cl-incf sum (string-to-number (match-string-no-properties 0))) ) (prog1 sum (message "sum: %.1f" sum) ))) (defalias 'di #'digits-sum) (defun film-mean () (interactive) (let ((scores) (beg (point-min)) (end (point-max)) ) (save-excursion (goto-char beg) (while (re-search-forward "[[:digit:]]" end t) (when (= (current-column) 73) (push (string-to-number (match-string-no-properties 0)) scores) ))) (when scores (message (format "%.3f" (mean-value scores))) ))) (defun positive-integer-p (n) (and (integerp n) (< 0 n) )) ;; (positive-integer-p 1.5) ; nil ;; (positive-integer-p 1) ; t ;; (positive-integer-p 0) ; nil ;; (positive-integer-p -1) ; nil (defun string-to-number-number (str) (let ((s (string-trim str))) (when (string-match-p "\\`[+-]?\\([[:digit:]]+\\|[[:digit:]]*\\.[[:digit:]]+\\)\\'" s) (string-to-number s) ))) (defun string-to-number-number-test () (cl-map 'list (lambda (e) (pcase-let ((`(,a ,b) e)) (if (and a b) (= a b) (eq a b) ))) (list (list (string-to-number-number " 10") 10) (list (string-to-number-number " 1.5") 1.5) (list (string-to-number-number " +0") 0) (list (string-to-number-number " 0") 0) (list (string-to-number-number " -0.0") -0.0) (list (string-to-number-number " -1.5") -1.5) (list (string-to-number-number "-10") -10) (list (string-to-number-number "123this used to work") nil) (list (string-to-number-number "NAN") nil) ))) ;; (string-to-number-number-test) (defun read-integer () (let ((str) (str-number) (n) ) (cl-loop until (progn (setq str (read-string "integer: ")) (if (string= str "0") (setq n 0) (setq str-number (string-to-number str)) (unless (= str-number 0) (setq n str-number) )) (integerp n)) ) n) ) ;; (read-integer) (defun compare (old new) (format "%.2f%%" (* 100 (/ (- old new) (* old 1.0) )))) ;; (compare 185 80) ; 56.76% (defun hypotenuse (c1 c2) (sqrt (+ (* c1 c1) (* c2 c2))) ) (defun speed (hour minute second km) (let*((s (+ second (* 60 minute) (* 60 60 hour))) (m (* 1000 km)) (mps (/ m s)) ) (* 3.6 mps) )) ;; (speed 04 44 10 42.195) ; 8.909208211143694 ;; (speed 02 01 39 42.195) ; 20.811344019728732 ;; (speed 19 04 00 168 ) ; 7.2 (defun binom (n k) (/ (cl-factorial n) (* (cl-factorial k) (cl-factorial (- n k)) ))) (defun product (l) (cl-loop with prod = 1 for i in l do (setq prod (* prod i)) finally return prod) ) ;; (product '(1 2 3 4)) ; 24 (defun tau-ceti (speed) (let*((dist (* 11.8 9.46 (expt 10 12))) (time (/ dist speed) ) (days (/ time 24)) (whole-days (round days)) ) (format-seconds "%y years" (- (float-time (encode-time 0 0 0 whole-days 0 0)) (float-time (encode-time 0 0 0 0 0 0)) )))) ;; (tau-ceti 5000) ; 2 548 584 years (provide 'math) -- underground experts united https://dataswamp.org/~incal