diff options
Diffstat (limited to 'lisp/calc')
-rw-r--r-- | lisp/calc/README | 293 | ||||
-rw-r--r-- | lisp/calc/README.prev | 998 | ||||
-rw-r--r-- | lisp/calc/calc-forms.el | 546 | ||||
-rw-r--r-- | lisp/calc/calc-graph.el | 1 | ||||
-rw-r--r-- | lisp/calc/calc-help.el | 20 | ||||
-rw-r--r-- | lisp/calc/calc-units.el | 96 | ||||
-rw-r--r-- | lisp/calc/calc.el | 66 |
7 files changed, 556 insertions, 1464 deletions
diff --git a/lisp/calc/README b/lisp/calc/README deleted file mode 100644 index 85181899f2a..00000000000 --- a/lisp/calc/README +++ /dev/null @@ -1,293 +0,0 @@ -Copyright (C) 2001-2013 Free Software Foundation, Inc. -See the end of the file for license conditions. - - -This directory contains Calc, an advanced desk calculator for GNU -Emacs. - -"Calc" Copyright (C) 1990-1993, 2001-2013 Free Software Foundation, Inc. - -Written by: - Dave Gillespie - c/o Synaptics, Inc. - 2698 Orchard Parkway - San Jose CA 95134 - daveg@synaptics.com, uunet!synaptx!daveg - -Currently maintained by: - Jay Belanger <jay.p.belanger@gmail.com> - -From the introduction to the manual: - - "Calc" is an advanced calculator and mathematical tool that runs as - part of the GNU Emacs environment. Very roughly based on the HP-28/48 - series of calculators, its many features include: - - * Choice of algebraic or RPN (stack-based) entry of calculations. - - * Arbitrary precision integers and floating-point numbers. - - * Arithmetic on rational numbers, complex numbers (rectangular and - polar), error forms with standard deviations, open and closed - intervals, vectors and matrices, dates and times, infinities, - sets, quantities with units, and algebraic formulas. - - * Mathematical operations such as logarithms and trigonometric functions. - - * Programmer's features (bitwise operations, non-decimal numbers). - - * Financial functions such as future value and internal rate of return. - - * Number theoretical features such as prime factorization and - arithmetic modulo M for any M. - - * Algebraic manipulation features, including symbolic calculus. - - * Moving data to and from regular editing buffers. - - * "Embedded mode" for manipulating Calc formulas and data directly - inside any editing buffer. - - * Graphics using GNUPLOT, a versatile (and free) plotting program. - - * Easy programming using keyboard macros, algebraic formulas, - algebraic rewrite rules, or extended Emacs Lisp. - - -Calc is written entirely in Emacs Lisp, for maximum portability. - -I am anxious to hear about your experiences using Calc. Send mail to -"jay.p.belanger@gmail.com". A bug report is most useful if you include the -exact input and output that occurred, any modes in effect (such as the -current precision), and so on. If you find Calc is difficult to operate -in any way, or if you have other suggestions, don't hesitate to let me -know. If you find errors (including simple typos) in the manual, let -me know. Even if you find no bugs at all I would love to hear your -opinions. - - - -Summary of changes to "Calc" -------- -- ------- -- ---- - -Emacs 24.3 - -Algebraic simplification mode is now the default. -To restrict to the limited simplifications given by the former -default simplification mode, use `m I'. - -Emacs 24.1 - -* Support for musical notes added. - -* Support for logarithmic units added. - -* Calc no longer uses the tex prefix for TeX specific unit -names when using TeX or LaTeX mode. - -* Added option to highlight selections using faces. - -* Gave `calc-histogram' the option of using a vector to determine the bins. - -* Added "O" option prefix. - -* Used "O" prefix to "d r" (`calc-radix') to turn on twos-complement mode. - -Emacs 23.2 - -* Added twos-complement display. - -Emacs 23.1: - -* Gave `j *' (cal-sel-mult-both-sides) an option to expand the - denominator. - -* Use `calc-embedded-word-regexp' for finding words in - `calc-embedded-word' in place of delimiters. - -* Remove version numbering; use Emacs version for reference. - -* Added support for using registers. - -* Added support for Yacas, Maxima and Giac languages. - -* Added a menu. - -* Added logistic non-linear curves to curve-fitting. - -* Added option of plotting data points and curve when curve-fitting. - -* Made unit conversions exact when possible. - -* Lowered the precedence of negation. - -Version 2.1: - -* New matrix mode for square matrices. Improved handling of - non-commutative products. - -* New functions: powerexpand and ldiv. - -* Added new functions: sec, csc, cot, sech, csch, coth. - -* 0^0 now evaluates to 1. - -* Added a new language mode for LaTeX. - -* Calc now tries to use an appropriate language mode in embedded mode. - -* Calc now restores original modes when leaving embedded mode. - -* User settable variables which are not set with keystrokes are now - customizable. - -* Made ~/.calc.el the default Calc settings file. - -* Miscellaneous updates and bugfixes. - - -Version 2.02f: - - * Fixed a bug which broke `I', `H', `K' prefix keys in recent Emacs. - - * Fixed a bug in calc.texinfo which prevented "make tex2" from working. - - * Updated `C-y' (calc-yank) to understand Emacs 19 generalized kill ring. - - * Added a copy of "calccard.tex", the Calc quick reference card. - - -Version 2.02e: - - * Fixed an installation bug caused by recent changes to `write-region'. - - -Version 2.02d: - - * Fixed a minor installation problem with a Emacs 19.29 byte-compiler bug. - - * Removed archaic "macedit" package (superseded by "edmacro"). - - -Version 2.02c: - - * Patch to port Calc to Lucid Emacs 19; still works with GNU 18 and GNU 19. - - * Fixed a bug that broke `C-x C-c' after Calc graphics had been used. - - -Version 2.02b: - - * Minor patch to port Calc to GNU Emacs 19. Will be superseded by Calc 3.00. - - -Version 2.02: - - * Revamped the manual a bit; rearranged some sections. - - * Added marginal notes for Key/Function Index refs in printed manual. - - * Changed `M-# r' to deal more gracefully with blank lines. - - * Made reductions like `V R +' and `M-# :' considerably faster. - - * Improved parsing and display of cases like "[a + b]". - - * Added `t +' and `t -' for doing business date arithmetic. - - * Added "syntax tables," the opposite of compositions. - - * Added another Rewrites Tutorial exercise. - - * Added the "vmatches" function. - - * Added the `Modes' variable and `m g' command. - - * Improved `u s' to cancel, e.g., "11 mph hr / yd" to get a number. - - * Added "quick units" commands "u 0" through "u 9". - - * Moved `M-%' to calc.el to avoid autoloading problems. - - * Added `M-=' during algebraic entry, acts like `RET ='. - - * Made `LFD' prevent evaluation when finishing a calc-edit command. - - * Changed calc-store commands to use `t .' mode for trail display. - - * Improved integrator to understand forms involving "erf". - - * Fixed parser to make sense of "[1....1e2]" input. - - * Fixed FORTRAN parser to treat a(i,j) as a_i_j if a is declared matrix. - - * Got rid of some version number stamps to reduce size of patches. - - * Fixed a bug in defmath treating "<=" and ">=" predicates. - - * Fixed a bug in which Calc crashed multiplying two date forms. - - * Fixed a bug in line breaker that crashed for large, nested formulas. - - * Fixed a bug using ` to edit string("foo"). - - * Fixed a bug where `M-# y' in Big mode copied stack level number. - - * Fixed a bug where `g O' used wrong default directory, no completion. - - * Fixed a bug where "foo_bar(i)" parsed in C mode but showed as foo#bar. - - * Fixed several bugs where large calculations got "computation too long." - - -Version 2.01: - - * Added percentage commands `M-%', `b %', and `c %'. - - * Changed Big mode to force radix-10 in superscripts. - - * Improved display of fractions in various language modes. - - * Changed `a n' to work properly with equations and inequalities. - - * The problem with cross references to Index nodes in TeX has been fixed. - - * Fixed a bug where recursive esc-maps make calc-ext/-aent unloadable. - - * Fixed a bug in `M-# k', then `OFF' right away, with fresh Emacs. - - * Fixed a bug in which "S_i_j" was formatted wrong after `j s'. - - * Fixed a bug in which `h k u c' positioned cursor on wrong line. - - * Fixed a bug where `z ?' crashed if `z %' was defined. - - * Fixed a bug in `j O' (calc-select-once-maybe). - - * Fixed "make private" not to ask "Delete excess versions" and crash. - - -Version 2.00: - - * First complete posting of Calc since 1.01. - - * Most parts of Calc have seen changes since version 1.07. See - section "New for Calc 2.00" in the manual for a summary. In - the FTP version of the Calc distribution, the file README.prev - contains a detailed change history from 1.00 up to 2.00. - - -This file is part of GNU Emacs. - -GNU Emacs is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -GNU Emacs is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. diff --git a/lisp/calc/README.prev b/lisp/calc/README.prev deleted file mode 100644 index eae72cbbe6c..00000000000 --- a/lisp/calc/README.prev +++ /dev/null @@ -1,998 +0,0 @@ -Copyright (C) 2001-2013 Free Software Foundation, Inc. -See the end of the file for license conditions. - - -Summary of changes to "Calc" Preceding 2.00 -------- -- ------- -- ---- --------- ---- - - -Version 2.00: - - * Changed to compile calc-macs/-maint, to allow "cp *.elc new-dir". - - * Improved calc-describe-bindings to avoid showing redundant ESC maps. - - -Version 2.00 beta 3: - - * Removed version numbers from most .el files to reduce size of patches. - - * Added a "calc-version" command. - - * Changed `M-# ? ?' to allow for modified describe-function. - - * Changed date parser to accept "Sept" as an alternative for "Sep". - - * Inhibited answers to exercise from showing up in table of contents. - - * Changed Makefile to say "texindex calc.[cfkptv]?" to avoid "calc.el". - - * Fixed up the Makefile in various other ways. - - * Rearranged banner at top of `h h' command's output. - - * Changed "make summary" to print "Calc Summary" on the title page. - - * Added "IntegSimpRules". - - * Added `M-# :', `M-# _', and `M-# Z' options. - - * Changed `^' to evaluate "[-3..-1]^-2" properly. - - * Improved `f g' to give symbolic answers for, e.g., 101:2 and -3:2. - - * Fixed a bug where `h k RET' didn't find the right place on the page. - - * Fixed a bug that formatted "x*(y ? a : b)" as "x y ? a : b". - - * Fixed a bug where defmath translated (< x 0) as (math-posp x)! - - * Fixed a bug that prevented quick-calc from working sometimes. - - * Fixed the `z ?' bug again (maybe this time for good?). - - * Fixed a bug in which `V ^' (vint) was just plain wrong, wrong, wrong! - - * Scanned for and fixed remaining bugs relating to autoloading. - - -Version 2.00 beta 2: - - * Changed "make info" to try "make texinfo" if "makeinfo" not found. - - * Changed to "New for Calc 2.00"; texinfo.tex chokes on apostrophes. - - * Added List Tutorial Exercise 14 (just in case there weren't enough!). - - * Added a discussion of the `Z F' command to the Programming Tutorial. - - * Improved `H a f' not to lose info if input is partially pre-factored. - - * Improved simplification of expressions like sqrt(3) + 3^3:2. - - * Changed Big mode to omit "*" in expressions like 2 sqrt(3) 5^3:4. - - * Replaced European date format D/M/Y with D.M.Y. - - * Changed `a N' and `a X' to consider the endpoints of the interval. - - * Fixed a bug where TeX mode made c*(1+a/b) look like a function call. - - * Fixed a bug formatting top-level evalto's while using selections. - - * Fixed a bug that caused `z ?' to crash. - - * Fixed a bug where `Z F' broke for argument names "t" and "nil". - - * Fixed several bugs relating to autoloading. - - -Version 2.00 beta 1: - - * Added "What's new in Calc 2.00" to the manual (summary of info below). - - * Added support for many GNUPLOT 3.0 features. - - * Tweaked the Makefile and calc-compile a bit more. - - * Modified to work with Zawinski's/Furuseth's optimizing byte compiler. - - * Modified Calc to garbage-collect less often (raised gc-cons-threshold). - - * Changed quick-calc to avoid autoloading so many parts of Calc. - - * Changed Calc subfiles to work properly if not byte-compiled. - - * Renamed `M-# s' to `M-# j', made `M-# s' be equivalent to `h s'. - - * Changed calc-quit to avoid reapportioning space among other windows. - - * Added `M-DEL' (calc-pop-above) key, to DEL as LFD is to RET. - - * Added `{' and `}' to scroll vertically, analogous to `<' and `>'. - - * Added `m t' for "total" algebraic mode. - - * Added `d , \' option to group digits with "\,". - - * Improved support of "prime" accent in "eqn" language mode. - - * Changed macedit's read-kbd-macro to accept a string argument in Lisp. - - * Changed calc-check-defines to use a more concise run-hooks linkage. - - * Changed auto-why mode not to say [w=more] if next msg is not urgent. - - * Made `a d' able to differentiate "a?b:c" and "a_i" formulas. - - * Changed probability dist. functions to work with `a f' and `a d'. - - * Added special constants "phi" and "gamma". - - * Added "poly" function, simpler cousin of "gpoly". - - * Added "pdeg", "plead", "pcont", "pprim"; cleaned up "pdiv" and "pgcd". - - * Added `a p' command for polynomial interpolation. - - * Added `a I' command for numerical integration; made IntegLimit variable. - - * Added `a f' to factor polynomials; moved old `a f' to `a "'. - - * Added `a a' to do partial fraction decompositions. - - * Improved `a i' to integrate many more kinds of formulas. - - * Modified `a P' to find numerical roots of high-degree polynomials. - - * Modified `c 0' through `c 9' to convert int-valued floats to integers. - - * Made sinh, arctanh, etc., expandable into exps/logs by `a f'. - - * Added more algebraic simplifications having to do with logs and exps. - - * Changed `s s', `s t', `s x', `s l' to accept an equation at prompt. - - * Changed `s i' not to store Decls if its value is the default, []. - - * Changed `s i' to store in `d O' language mode if in Normal or Big mode. - - * Rearranged `V M'/`V R' matrix mapping modes. - - * Added <#1+#2> notation for lambda expressions. - - * Extended `b l' and other binary shifts to have a 2-argument version. - - * Changed `u c' and `u t' to give unitless result for unitless input. - - * Changed sqrt(1-cos(x)^2)-to-sin(x) to be an unsafe simplification. - - * Improved simplification of sqrts, e.g., sqrt(a^2 x + a^2 y). - - * Changed solver to treat (x-a)(x-b)(x-c) more intelligently. - - * Changed Pascal language mode to use "$FFFF" for hexadecimal numbers. - - * Added support for non-decimal display of floats. - - * Changed `p' to refresh stack display if current float format uses it. - - * Changed Big mode to use subscript notation for log10(x), log(x,b), r#nnn. - - * Changed Big mode to format deriv(u,x) and tderiv(u,x) as du/dx. - - * Changed Big mode to format integ(1/x,x) as "dx/x" instead of "1/x dx". - - * Added "tty" output type for graphics commands. - - * Documented Calc's random number generation algorithm in the manual. - - * Fixed a bug involving having "(setq calc-timing t)" in .emacs. - - * Fixed a bug that incorrectly parsed "|x| - 1" in TeX mode. - - * Fixed bugs and made improvements in `a R' when widening the guess. - - * Fixed a bug that where `a S' didn't solve (x - a)^2 = (x - b)^2. - - * Fixed a bug that sometimes crashed `a P' on systems of equations. - - * Fixed a bug that prevented `b p' (calc-pack-bits) from working. - - * Fixed some bugs in which certain functions didn't get autoloaded. - - * Fixed a bug in which the date <1/1/13> was incorrectly parsed. - - * Fixed a bug which prevented `j D' from expanding (a+b)/c. - - * Fixed a bug in solver: bad inverses for sinh and cosh. - - * Fixed a bug in math-possible-signs that failed for x*0. - - * Fixed a bug where sqrt(-a) was rewritten sqrt(a)*i even if a<0. - - * Fixed a bug in line breaker when first "word" of line was too long. - - * Worked around a makeinfo bug that handled @end group/@group badly. - - -Version 2.00 alpha 3: - - * Changed logic for locating component .elc files to be even smarter. - - * Changed "make install" to "make compile"; added different "make install". - - * Improved "make compile" to check file dates and compile only when needed. - - * Made output of "make compile" in batch mode more compact and readable. - - * Replaced "Quick Overview" in manual with "Demonstration of Calc". - - * Changed to use keymaps for dispatching M-# and h prefix keys. - - * Added TAGS target to the Calc Makefile. - - * Removed most doc strings from functions; new help commands are better. - - * Got rid of some crufty "fset" calls that were cluttering the code. - - * Split calc-grab-region into two functions, calc-grab-region/-rectangle. - - * Swapped positions of stack and trail in full-calc-keypad display. - - * Improved line-breaking algorithm for displaying long formulas. - - * Improved display of control characters in vectors shown as strings. - - * Changed `d o' to allow fraction format to specify desired denominator. - - * Changed `M-# y' to respect overwrite mode in target buffer. - - * Added `H' prefix to display-mode commands to suppress stack refresh. - - * Changed "calc-why" mechanism to display urgent messages automatically. - - * Handled taking derivatives of symbolic integrals and vice-versa. - - * Handled integrating vectors of formulas. - - * Incorporated Ewerlid's polynomial division and GCD functions into Calc. - - * Improved algebraic operations on "mod" forms, esp. polynomials. - - * Added some more financial functions (sln, syd, ddb). - - * Added nest, anest, fixp, and afixp (`H V R' and `H V U') functions. - - * Added `a .' (calc-remove-equal) command to take apart equations. - - * Generalized dfact to work for negative odd integers; added !! syntax. - - * Changed `k f' to factor 1, 0, and negative integers. - - * Changed `u M', etc., to accept +/- and [ .. ] forms as distributions. - - * Changed `g q' to remove *Gnuplot Commands/Trail* window if present. - - * Added support for Francois Pinard's "dumb terminal" driver for GNUPLOT. - - * Added ":: remember" feature for rewrite rules. - - * Changed rewrites to let pattern "a*b" match "x/2" with a=x, b=1/2. - - * Added ability to put function names like "simplify" in rewrite schedule. - - * Added "Rewrites Tutorial" to the manual. - - * Changed ` to bind RET as newline instead of finish if editing a vector. - - * Added some new exercises to the List Tutorial. - - * Changed `Z F', `V M', etc. not to remove stored vars from def arg list. - - * Added parsing for /1, 2, 3/ notation for Fortran mode vectors. - - * Added a "%%" syntax for comments in formulas being read. - - * Fixed a bug in which failing `h k' removed an existing Info window. - - * Fixed a bug in `j /' operating on subformulas like "a + b". - - * Fixed a bug in which "inf = inf" undesirably evaluated to 1. - - * Fixed a bug that simplified "0 = 1 + a + 2" to "0 = a". - - * Fixed a bug that failed for rewrite patterns like "fib(1 ||| 2)". - - * Fixed a bug that arose because rewrite programs are non-reentrant. - - -Version 2.00 alpha 2: - - * Changed LFD terminating algebraic entry to push in no-simplify mode. - - * Changed so that `K -' interprets `-' as calc-minus, not neg prefix arg. - - * Improved `h c' command to understand all Calc key sequences. - - * Fixed problems with DistribRules, NegateRules, and FitRules. - - * Fixed several bad node pointers in the manual. - - * Fixed a bug in `h C-w' when used with makeinfo-formatted manuals. - - * Fixed a bug in sqrt(-1) when Polar and HMS modes are enabled. - - * Fixed/improved dscalar and deven functions; added dodd. - - * Fixed a bug in polynomial handling that also affected sum(sin(k),k,1,n). - - * Fixed various other glitches in the manual. - - -Version 2.00 alpha 1: - - * Calc's tar file now creates a calc-(version) directory to unpack into. - - * Calc now comes with a Makefile; install with "make install". - - * Calc now comes already split into many files; installation is much simpler. - - * Changed base file name of the manual from "calc-info" to "calc.info". - - * Key binding for `M-# w' was documented but not implemented. - - * Bound M-# ' to be synonymous with `M-# f' (used to be `M-# q'). - - * Changed M-# M-# to use last interface of C or K; E no longer counts. - - * Changed `i' (and `M-# i') not to return to Top node unnecessarily. - - * Changed `h' to be a prefix key with various help commands. - - * Changed `s' to be a prefix key with various store and recall commands. - - * Keys `i', `r', and `l' are obsolete (moved to `h' and `s' prefixes). - - * Rearranged `K', `X', and `M-RET' keys; `K' is now calc-keep-args. - - * Changed quick-calc to display input formula as well as output if room. - - * Changed quick-calc to interact with the editing buffer and kill ring. - - * Created pack, unpack, unpackt function equivalents of `v p', `v u'. - - * Changed to expand (a/b)^x to a^x/b^x only if b > 0 (not if a > 0). - - * Changed math-possible-signs to understand sqrt function. - - * Changed Z [, rewrites to consider any provably non-zero value as true. - - * Changed normal language modes to accept ** as a synonym for ^. - - * Added "maple" language mode. - - * Changed, e.g., Mathematica "(2 + 3 I)^(1.23*10^20)" to include parens. - - * Generalized math-compose-big properties for all language modes. - - * Introduced "string" and other function for composing expressions. - - * Changed many recursive vector routines to use loops instead. - - * Added evalv, evalvn function equivalents to `=', `N'. - - * Changed "expr =>" not to evaluate at all if in no-simplify mode. - - * Redesigned user interface of `a F' (calc-curve-fit) command. - - * Added "phase" feature to the rewrite rule system. - - * Added "&&&", "|||", "!!!" to the rewrite rule system. - - * Introduced a new notation for rewrites: LHS := RHS :: COND. - - * Changed `a r' (but not `j r') to repeat 100 times by default. - - * Integrated EvalRules more cleanly into the default simplifications. - - * Added `H v l' [mdims] to measure the dimensions of a matrix. - - * Changed `u c' to interpret "/units" as "1/units". - - * Added `u a' to adjust unit prefix letters automatically. - - * Changed `u s' to enable scalar mode while simplifying. - - * Changed `c f' [pfloat] not to float integer powers or subscripts. - - * Added a three-argument form for the "hms" function. - - * Changed, e.g., sin(90) degrees to produce 1 instead of 1.0. - - * Changed symbolic mode to prefer sqrt(int): abs([1 2 3]) => sqrt(14). - - * Enhanced solver to handle, e.g., x + 1/x = a; exp(x) + exp(-x) = a. - - * Enhanced simplifier to handle, e.g., exp(a+2) / e^a => e^2. - - * Enhanced `a s' to simplify sqrt(x) - x^1:2 and exp(x) - e^x to 0. - - * Added -(a + b) to -a - b as a default simplification. - - * Added rules for differentiating sum() and prod() functions. - - * Added a few more energy units (due to Przemek Klosowski). - - * Added overflow/underflow checking for all floating-point arithmetic. - - * Extended error forms to work with complex numbers. - - * Generalized GCD to handle fractional arguments. - - * Changed graphics routines to evaluate "x" values, e.g., [-pi .. pi]. - - * Added `g q', like `g K' but without viewing the Gnuplot Trail. - - * Changed `g p' and `V M' to display better "Working..." messages. - - * Modified `M-# g' to be more robust about grabbing formulas. - - * Added `Y' prefix key reserved for user-written extensions. - - * Added calc-load-hook and calc-ext-load-hook. - - * Prevented calc-install from leaving large ~ files behind. - - * Changed @bullet to @bullet{} in manual to conform to texinfo spec. - - * Rearranged some chapters in the manual to be a bit more logical. - - * Added calc-split-summary command. - - * Fixed several bugs in embedded mode. - - * Fixed a bug in calc-vector-covariance that required a prefix arg. - - * Fixed a bug that prevented parsing "a=>" with no right-hand side. - - * Fixed a bug which allowed incorrectly dividing a vector by a vector. - - * Fixed a bug formatting sum(...)^2 in Big mode. - - * Fixed a bug that prevented Calc from deleting old graphics temp files. - - * Fixed some typos calling calc-inverse-func instead of calc-invert-func. - - * Fixed bugs in the derivatives of conj, deg, and rad; added re, im. - - * Fixed a bug where (r;theta) parsed as r exp(theta i) even in Deg mode. - - * Fixed a bug which gave wrong answer for exp of a polar complex number. - - * Fixed a bug in `Z F' that failed if formula used non-arg variables. - - * Fixed a bad pointer to Info node "Assignments in Embedded Mode". - - * Fixed several errors in the Calc Summary. - - -Version 1.08 beta 1: - - * Calc's copyright has been assigned to FSF, for inclusion in Emacs 19! - - * Changed M-# to be a two-key sequence; use M-# M-# to start Calc now. - - * Rewrote and expanded the introductory chapter of the manual. - - * Added a key and function summary to the manual. - - * Changed the manual to take better advantage of TeX's math formatting. - - * Changed manual to be printable in @smallbook format. - - * Added "calc-embedded" mode. - - * Added "=>" [evalto] operator. - - * Added facilities for date and date/time arithmetic. - - * Added a set of financial functions (pv, fv, etc.). - - * Added infinite quantities inf, uinf, and nan (plus infinite intervals). - - * Added "EvalRules", "SimpRules", and "ExtSimpRules" variables. - - * Added sum and product commands `a +', `a -', `a *', `a T'. - - * Enhanced `a S' and `a P' to solve systems of equations. - - * Enhanced solver to handle eqns like sin(x) = cos(2 x), sqrt(x) + x = 1. - - * Added `a M' (calc-map-equation) command. - - * Added new statistical functions: mean, standard deviation, etc. - - * Added line, polynomial, and curve fitting commands (`a L' and `a F'). - - * Added support for composite units, e.g., "mi+ft+in". - - * Enhanced "Big" mode to format square roots, choose, and powers better. - - * Enhanced "Big" mode to display fractions in large notation. - - * Added several alternate formats for matrix display. - - * Changed TeX mode to write "(1 + x^2)" instead of "\left(1 + x^2\right)". - - * Added support for relational operators in TeX and FORTRAN modes. - - * Added recognition of accents like \dot, \tilde, \underline in TeX mode. - - * Added "eqn" language mode. - - * Added extra control over display justification with `d <', `d =', `d >'. - - * Added calc-left-label and calc-right-label (`d {', `d }'). - - * Added "nn%" syntax for algebraic formulas; equivalent to "nn * .01". - - * Added input syntaxes like a = b = c, a != b != c, a <= b < c. - - * Changed "_" to mean subscripts; old use of "_" in vars is now "#". - - * Introduced "matrix mode" and "scalar mode" (`m v'). - - * Introduced generic identity matrices (idn(1)). - - * Added a method for declaring variables to be real, integer, > 0, etc. - - * Added `Z S' command for editing stored value of a variable. - - * Added "subst" algebraic function equivalent to the `a b' command. - - * Added `a f' command, changed deriv/integ/solve-for to use it. - - * Improved `a s' to simplify (x + y) (y + x) to (x + y)^2. - - * Improved `a s' to simplify i^2 to -1. - - * Improved `a s' to simplify, e.g., sin(pi/3) in Symbolic mode. - - * Improved `a s' to simplify sqrt(8) to 2 sqrt(2), 1/sqrt(2) to sqrt(2)/2. - - * Moved sin(arccos(x)) from `a e' to `a s'; not unsafe after all! - - * Changed (x y)^z => x^z y^z to be a usually-unsafe simplification. - - * Added thorough documentation of `a s' and `a e' to the manual. - - * Improved `a c' to collect "f(a)" even if "a" also appears elsewhere. - - * Introduced lin, linnt, islin, islinnt functions for linearity testing. - - * Improved `a x' to use binomial theorem to give simpler answers. - - * Improved `j D' to distribute powers of sums: (a + b)^n. - - * Improved `j M' to merge products of powers (may need no-simplify mode). - - * Changed to use defvar for DistribRules etc. so `Z V' works with them. - - * Improved `j *' and `j /' to work properly in a few more cases. - - * Improved `V R' to use identity value when reducing empty vectors. - - * Improved `v p' and `v u' to support more complex packing operations. - - * Disabled automatic simplification of sqrt(2)/2 to 1/sqrt(2). - - * Bound SPC and RET to press, TAB to next-menu in *Calc Keypad* buffer. - - * Added C-u ' to do algebraic entry with language mode forced to normal. - - * Added "$1", "$2", etc. input notation for algebraic entry. - - * Changed unary operators like `n', `&' to treat neg prefix args like RET. - - * Changed ` (calc-edit) to show full precision regardless of float format. - - * Enhanced quick-calc to display integers in several formats. - - * Documented `g H' (calc-graph-hide) command (had been left from manual). - - * Enhanced floor/ceil/trunc/round in several ways. - - * Added rounde and roundu functions. - - * Changed `c 1' through `c 9' to change small floats to 0.0; added `c 0'. - - * Enhanced set operations to work on sets of intervals. - - * Fixed erf(0), utpn(x,x,y), and arccosh(-1) to work properly. - - * Changed complex arctan and arctanh to follow Steele 2nd edition. - - * Expanded "Branch Cuts" section of the manual with some useful tables. - - * Rearranged order of words in mode line to be a bit more logical. - - * Changed `m N' (num-simplify) mode to evaluate constant vectors, too. - - * Changed `a r'/`j r' to prompt twice for separate LHS/RHS if necessary. - - * Enhanced `let(v,x)' in rewrites by allowing arbitrary patterns for v. - - * Changed cursor positioning in second prompt for `a b' (calc-substitute). - - * Changed `y' to omit line numbers more consistently. - - * Changed `o' (calc-realign) to reset horizontal scrolling to zero, also. - - * Added "pred" mode for calc-eval. - - * Added "calc-report-bug" as an alias for "report-calc-bug". - - * Added `Z T' and "calc-pass-errors" to aid debugging Calc-related code. - - * Added "calc-load-everything" (`m X' or `M-# L') command. - - * Enhanced calc-install to pre-build units table, CommuteRules, etc. - - * Changed Calc to interact more gracefully with load-path. - - * Changed Lisp Variable Index in manual to include user variables, too. - - * Fixed a bug that prevented calc-install from working under VMS. - - * Fixed a bug that sometimes crashed rewrites dealing with subtractions. - - * Fixed a bug that prevented `a S' from solving "3 - x = 1 + x"! - - * Fixed a bug in solver that crashed for certain cubics and quartics. - - * Fixed a bug in calc-simplify that crashed for equations and ineqs. - - * Fixed a bug which placed the "[" oddly in `d B' + `v /' mode. - - * Fixed a bug where finishing calc-edit improperly obeyed language mode. - - * Fixed a bug formatting (-1)^n in Big mode after selection commands. - - * Fixed a bug that got ">=" and "<=" backwards in rewrite conditions. - - * Fixed a bug that broke the `"x"' key in calc-keypad mode. - - * Fixed a bug in which `MAP$' in calc-keypad didn't display "Working...". - - * Fixed a bug where matrix division gave bad result for singular matrix. - - * Fixed a bug which closed Calc window if calc-grab-region got an error. - - * Fixed a bug where `a s' failed on formulas containing dimension errors. - - * Fixed a bug that caused `m F' to hang. - - * Fixed a bug in complex arithmetic that caused problems with solver. - - * Fixed a bug which raised intervals to interval powers incorrectly. - - * Fixed a bug in utpp/ltpp (order of arguments did not match the manual). - - * Fixed a bug in which `t y' rounded yanked data with old precision. - - * Fixed a bug in which "in(3, [3 .. 3))" returned true. - - * Fixed a bug which simplified abs(abs(x)) incorrectly. - - * Fixed a bug in which (a^2)^1:3 was unsafely simplified to a^2:3. - - * Fixed a bug in rewrite system which missed pattern "2 sin(x) cos(x)". - - * Fixed a bug in rewrite system which missed pattern "a - a cos(x)^2". - - * Fixed obsolete trail tags gsmp, gneg, ginv to jsmp, jneg, jinv. - - * Fixed some errors and made improvements in units table [Ulrich Mueller]. - - -Version 1.07: - - * Added `m F' (calc-settings-file-name) command. - - * Added calc-autoload-directory variable. - - * Extended Z ` to accept a prefix argument. - - * Added keystrokes (v h, v k) for head, tail, cons. - - * Extended `v e' to accept a vector as the filler. - - * Changed `V M', `V R' to accept mapping-mode keys in uppercase, too. - - * Changed V M ' etc. to accept $, $$, ... as argument indicators. - - * Changed `t y' to accept a prefix argument. - - * Put in a cleaner and safer random number generator for `k r' et al. - - * Fixed a bug which completely broke `a r' command! - - * Fixed "0 * matrix" to generate a zero matrix instead of 0. - - * Fixed a bug in `a R' which sometimes caused it to crash. - - * Fixed a fatal typo in the TeX version of the manual. - - * Fixed a bug that prevented C-k, C-w, M-w from working in Trail buffer. - - * Fixed another bug in `Z P' command. - - * Fixed a bug in `u s' which incorrectly simplified subtractions. - - * Fixed an argument-name aliasing bug evaluating lambda( ) formulas. - - * Fixed overfull hboxes in the manual. - - * Fixed various other bugs in the manual. - - -Version 1.06: - - * Added "calc-keypad" mode for X window system users (try it!). - - * Improved "calc-eval" for calling/operating Calc from user-written Lisp. - - * Moved vector accumulate command to `V U' (old `H V R' still supported). - - * Added right-to-left reductions: `I V R' and `I V U'. - - * Added set operations on vectors: intersect, union, diff, xor. - - * Added `I v s' to remove a subvector from a vector. - - * Introduced `H |' to append two vectors with no magical special cases. - - * Introduced rhead, rtail, and rcons for isolating last vector element. - - * Changed `g p' to keep temp files around until data actually change. - - * Improved `a S' to solve many higher-order polynomial equations. - - * Added `a P' to produce a vector of all solutions to an equation. - - * Enhanced `a v' and `j v' to allow top-level-only evaluation. - - * Changed `j DEL' to delete a side of an eqn or ineq, leaving other side. - - * Fixed binding for keys `j 1' through `j 9'. - - * Introduced "let" marker in rewrite rules. - - * Enhanced the "sign" function to provide a two-argument version. - - * Changed "max-specpdl-size exceeded" error message to be user-friendly. - - * Put "<Aborted>" in the trail in above case and when user presses C-g. - - * Changed TeX mode to generate \ldots instead of \dots, recognize both. - - * Changed "sin(0)" etc. (for integer 0) to generate "0" instead of "0.". - - * Enhanced Programming Tutorial exercise 2. - - * Fixed an error in the answer to Types Tutorial exercise 3. - - * Fixed several bugs relating to head, tail, and cons functions. - - * Fixed some other minor typos in the manual. - - * Fixed several bugs in `Z P' (calc-user-define-permanent). - - * Fixed several bugs that broke the `g P' command. - - -Version 1.05: - - * Created a calc-install command to ease installation. - - * Added lots of exercises to the Tutorial section of the manual. - - * Added ability to select and operate on sub-formulas. - - * Substantially improved the algebraic rewrite-rule system. - - * Added a set of graphing commands that use GNUPLOT. - - * Added a command (`a R') for finding numerical roots to equations. - - * Added several new math functions, such as erf and Bessel functions. - - * Added key bindings for miscellaneous commands using the "f" prefix key. - - * Added lots of new vector operations, many of them in the spirit of APL. - - * Added more control over vector display, including an abbreviated mode. - - * Improved keyboard macro editing; added read-kbd-macro to macedit.el. - - * Introduced the `m S' (calc-shift-prefix) command. - - * Enhanced the calc-edit command in several ways. - - * Made it possible to hit ` (calc-edit) during numeric/algebraic entry. - - * Enhanced the calc-solve-for command to handle inequalities. - - * Enhanced calc-simplify to handle equations and inequalities. - - * Taught log10 and log to look for exact integer or rational results. - - * Added ability to take Nth roots directly. - - * Added "increment" and "decrement" commands for integers and floats. - - * Added "full-help" command, changed "h" key to invoke it. - - * Added special help for Inverse and Hyperbolic prefixes. - - * Added an optional prefix argument to `o' (calc-realign). - - * Changed `t s' and `t r' to use RET as the search exit key. - - * Made handling of operator keys for V M, V R, etc. more regular. - - * Improved TeX mode; added support for \matrix format. - - * Added a variant of `m a' mode that only affects ( and [ keys. - - * Fixed "Mismatch" message for algebraic entry of semi-open intervals. - - * Trimmed fat from calc.el to speed loading, moved more to calc-ext.el. - - * Fixed a bug in which minibuffer entry rounded to out-of-date precision. - - * Fixed a bug which crashed Calc 1.04 under Epoch. - - * Fixed a bug which messed up Calc Trail's mode line, among other things. - - * Fixed a bug which caused trail ">" to show only when in Trail buffer. - - * Fixed a bug in which "calc" called "calc-grab-region" with too few args. - - * Fixed bugs in both implementation and documentation of calc-perm. - - * Fixed a bug in which calc-simplify-extended always used radians. - - * Fixed a bug where calc-comma failed to override "polar" mode. - - * Fixed a bug doing mixed arithmetic on rectangular+polar complex numbers. - - * Fixed several bugs in transcendental functions with complex arguments. - - * Fixed a bug in which `a s' simplified "x / .5" to ".5 x". - - * Fixed numerous other bugs in various parts of Calc. - - * Completed the "Hooks" section of the "Internals" chapter of the manual. - - -Version 1.04: - - * Included a copy of revision history (from README) in calc.el. - - * Added the "calc-split" feature to split calc-ext.el into smaller bits. - - * Changed calc-unpack to unpack floats and fractions, too. - - * Added "mant", "xpon", and "scf" functions for decomposing floats. - - * Fixed a bug in the "y" command with positive prefix arguments. - - * Rearranged binary shift/rotate command keys to be a bit more convenient. - - * Fixed a bug in which simplifying "(0/0) * 2" crashed with a Lisp error. - - * Made `H F' [ffloor] and friends faster for very large arguments. - - * Made calc-define-del more robust. - - * Handled pasting of data into the Calculator using the mouse under X. - - * Made overlay-arrow variables buffer-local to avoid interference. - - * Fixed a problem in which Calc Trail buffer got stuck after a C-x C-w. - - -Version 1.03: - - * Changed math-choose to compute n-choose-m faster when m is large. - - * Fixed some problems with TeX mode. - - * Fixed a bug that prevented `b s' from working without a prefix argument. - - * Added "calc-eval" function. - - * Improved calc-grab-region. - - -Version 1.02: - - * Fixed a bug in Tutorial: telephone pole height/distance were switched! - - * Fixed a few other things in the manual. - - * Added "full-calc" command. - - * Added "calc-insert-variables" (`Z I') command. - - * Quick Calc now works even if you are already in the minibuffer. - - * Fixed a bug in math-mul-bignum-digit which affected math-and, etc. - - * Definition of "Hectares" was wrong in units table. - - * Fixed a bug in calc-execute-kbd-macro concerning undo and refresh. - - * Bound "calc-undo" to `C-x u' as well as `C-_' and `U'. - -Version 1.01: - - * Added a tutorial section to the manual. - - * Next and Prev for node Strings in the manual were reversed; fixed. - - * Changed "'bignum" in calc-isqrt-bignum-iter to "'bigpos". - - * Fixed a bug that prevented "$" from working during algebraic entry. - - * Fixed a bug caused by an X (last-X) command following a K (macro) cmd. - - * Fixed a bug in which K command incorrectly formatted stack in Big mode. - - * Added space between unary operators and non-flat compositions. - (Otherwise, "-(a/b)" in Big mode blended the minus sign into the rule!) - - * Fixed formatting of (-1)^n in Big mode. - - * Fixed some problems relating to "not" operator in Pascal language mode. - - * Fixed several bugs relating to V M ' and V M $ sequences. - - * Fixed matrix-vector multiplication to produce a vector. - - * Introduced Z ` ... Z ' commands; renamed old Z ' to Z #. - - * Fixed various other bugs. - - * Added calc-settings-file variable suggested by C. Witty. - - -Version 1.00: - - * First official release of Calc. - - * If you used the Beta test version (0.01), you will find that this - version of Calc is over 50% larger than the original release. - General areas of improvement include much better algebra features; - operations on units; language modes; simplification modes; interval - arithmetic; vector mapping and reduction. Other new commands include - calc-fraction and calc-grab-region. The program has been split into - two parts for faster loading, and the manual is more complete. - - -This file is part of GNU Emacs. - -GNU Emacs is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -GNU Emacs is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. diff --git a/lisp/calc/calc-forms.el b/lisp/calc/calc-forms.el index e14d2c8d215..77efb1efc84 100644 --- a/lisp/calc/calc-forms.el +++ b/lisp/calc/calc-forms.el @@ -82,19 +82,20 @@ (calc-wrapper (if (string-match-p "\\`\\s-*\\'" fmt) (setq fmt "1")) - (if (string-match "\\` *[0-9] *\\'" fmt) + (if (string-match "\\` *\\([0-9]\\|10\\|11\\) *\\'" fmt) (setq fmt (nth (string-to-number fmt) calc-standard-date-formats))) (or (string-match "[a-zA-Z]" fmt) (error "Bad date format specifier")) (and arg (>= (setq arg (prefix-numeric-value arg)) 0) - (<= arg 9) + (<= arg 11) (setq calc-standard-date-formats (copy-sequence calc-standard-date-formats)) (setcar (nthcdr arg calc-standard-date-formats) fmt)) (let ((case-fold-search nil)) (and (not (string-match "<.*>" fmt)) - (string-match "\\`[^hHspP]*\\([^ac-gi-lnoqrt-zAC-GI-OQRT-Z]*[bBhHmpPsS]+[^ac-gi-lnoqrt-zAC-GI-OQRT-Z]*\\)[^hHspP]*\\'" fmt) + ;; Find time part to put in <...> + (string-match "\\`[^hHspPT]*\\([^ac-gi-lnoqrt-zAC-GI-OQRU-Z]*\\(bs\\|bm\\|bh\\|BS\\|BH\\|[hHmpPsST]\\)+[^ac-gi-lnoqrt-zAC-GI-OQRU-Z]*\\)[^hHspPT]*\\'" fmt) (string-match (concat "[^ac-gi-lnoqrt-zAC-GI-OQRT-Z]*" (regexp-quote (math-match-substring fmt 1)) "[^ac-gi-lnoqrt-zAC-GI-OQRT-Z]*") fmt) @@ -125,7 +126,7 @@ lfmt nil)) (setq time nil)) (t - (if (string-match "\\`[^a-zA-Z]*[bB][a-zA-Z]" fmt) + (if (string-match "\\`[^a-zA-Z]*[bBZI][a-zA-Z]" fmt) (setq pos2 (1+ pos2))) (while (and (< pos2 (length fmt)) (= (upcase (aref fmt pos2)) @@ -133,6 +134,7 @@ (setq pos2 (1+ pos2))) (setq sym (intern (substring fmt pos pos2))) (or (memq sym '(Y YY BY YYY YYYY + ZYYY IYYY Iww w aa AA aaa AAA aaaa AAAA bb BB bbb BBB bbbb BBBB M MM BM mmm Mmm Mmmm MMM MMMM @@ -140,8 +142,8 @@ W www Www Wwww WWW WWWW h hh bh H HH BH p P pp PP pppp PPPP - m mm bm s ss bss SS BS C - N n J j U b)) + m mm bm s ss bs SS BS C + N n J j U b T)) (and (eq sym 'X) (not lfmt) (not fullfmt)) (error "Bad format code: %s" sym)) (and (memq sym '(bb BB bbb BBB bbbb BBBB)) @@ -369,17 +371,68 @@ ;;; Some of these functions are adapted from Edward Reingold's "calendar.el". ;;; These versions are rewritten to use arbitrary-size integers. -;;; The Julian calendar is used up to 9/2/1752, after which the Gregorian -;;; calendar is used; the first day after 9/2/1752 is 9/14/1752. ;;; A numerical date is the number of days since midnight on -;;; the morning of January 1, 1 A.D. If the date is a non-integer, -;;; it represents a specific date and time. +;;; the morning of December 31, 1 B.C. (Gregorian) or January 2, 1 A.D. (Julian). +;;; Emacs's calendar refers to such a date as an absolute date, some Calc function +;;; names also use that terminology. If the date is a non-integer, it represents +;;; a specific date and time. ;;; A "dt" is a list of the form, (year month day), corresponding to ;;; an integer code, or (year month day hour minute second), corresponding ;;; to a non-integer code. +(defun math-date-to-gregorian-dt (date) + "Return the day (YEAR MONTH DAY) in the Gregorian calendar. +DATE is the number of days since December 31, -1 in the Gregorian calendar." + (let* ((month 1) + day + (year (math-quotient (math-add date (if (Math-lessp date 711859) + 365 ; for speed, we take + -108)) ; >1950 as a special case + (if (math-negp date) 366 365))) + ; this result may be an overestimate + temp) + (while (Math-lessp date (setq temp (math-absolute-from-gregorian-dt year 1 1))) + (setq year (math-add year -1))) + (if (eq year 0) (setq year -1)) + (setq date (1+ (math-sub date temp))) + (setq temp + (if (math-leap-year-p year) + [1 32 61 92 122 153 183 214 245 275 306 336 999] + [1 32 60 91 121 152 182 213 244 274 305 335 999])) + (while (>= date (aref temp month)) + (setq month (1+ month))) + (setq day (1+ (- date (aref temp (1- month))))) + (list year month day))) + +(defun math-date-to-julian-dt (date) + "Return the day (YEAR MONTH DAY) in the Julian calendar. +DATE is the number of days since December 31, -1 in the Gregorian calendar." + (let* ((month 1) + day + (year (math-quotient (math-add date (if (Math-lessp date 711859) + 367 ; for speed, we take + -106)) ; >1950 as a special case + (if (math-negp date) 366 365))) + ; this result may be an overestimate + temp) + (while (Math-lessp date (setq temp (math-absolute-from-julian-dt year 1 1))) + (setq year (math-add year -1))) + (if (eq year 0) (setq year -1)) + (setq date (1+ (math-sub date temp))) + (setq temp + (if (math-leap-year-p year t) + [1 32 61 92 122 153 183 214 245 275 306 336 999] + [1 32 60 91 121 152 182 213 244 274 305 335 999])) + (while (>= date (aref temp month)) + (setq month (1+ month))) + (setq day (1+ (- date (aref temp (1- month))))) + (list year month day))) + (defun math-date-to-dt (value) + "Return the day and time of VALUE. +The integer part of VALUE is the number of days since Dec 31, -1 +in the Gregorian calendar and the remaining part determines the time." (if (eq (car-safe value) 'date) (setq value (nth 1 value))) (or (math-realp value) @@ -387,32 +440,42 @@ (let* ((parts (math-date-parts value)) (date (car parts)) (time (nth 1 parts)) - (month 1) - day - (year (math-quotient (math-add date (if (Math-lessp date 711859) - 365 ; for speed, we take - -108)) ; >1950 as a special case - (if (math-negp value) 366 365))) - ; this result may be an overestimate - temp) - (while (Math-lessp date (setq temp (math-absolute-from-date year 1 1))) - (setq year (math-add year -1))) - (if (eq year 0) (setq year -1)) - (setq date (1+ (math-sub date temp))) - (and (eq year 1752) (>= date 247) - (setq date (+ date 11))) - (setq temp (if (math-leap-year-p year) - [1 32 61 92 122 153 183 214 245 275 306 336 999] - [1 32 60 91 121 152 182 213 244 274 305 335 999])) - (while (>= date (aref temp month)) - (setq month (1+ month))) - (setq day (1+ (- date (aref temp (1- month))))) + (dt (if (and calc-gregorian-switch + (Math-lessp value + (or + (nth 3 calc-gregorian-switch) + (apply 'math-absolute-from-gregorian-dt calc-gregorian-switch)) +)) + (math-date-to-julian-dt date) + (math-date-to-gregorian-dt date)))) (if (math-integerp value) - (list year month day) - (list year month day - (/ time 3600) - (% (/ time 60) 60) - (math-add (% time 60) (nth 2 parts)))))) + dt + (append dt + (list + (/ time 3600) + (% (/ time 60) 60) + (math-add (% time 60) (nth 2 parts))))))) + +(defun math-date-to-iso-dt (date) + "Return the ISO8601 date (year week day) of DATE." + (unless (Math-integerp date) + (setq date (math-floor date))) + (let* ((approx (nth 0 (math-date-to-gregorian-dt (math-sub date 3)))) + (year (math-add approx + (let ((y approx) + (sum 0)) + (while (>= (math-compare date + (math-absolute-from-iso-dt (setq y (math-add y 1)) 1 1)) 0) + (setq sum (+ sum 1))) + sum)))) + (list + year + (math-add (car (math-idivmod + (math-sub date (math-absolute-from-iso-dt year 1 1)) + 7)) + 1) + (let ((day (calcFunc-mod date 7))) + (if (= day 0) 7 day))))) (defun math-dt-to-date (dt) (or (integerp (nth 1 dt)) @@ -423,7 +486,17 @@ (math-reject-arg (nth 2 dt) 'fixnump)) (if (or (< (nth 2 dt) 1) (> (nth 2 dt) 31)) (math-reject-arg (nth 2 dt) "Day value is out of range")) - (let ((date (math-absolute-from-date (car dt) (nth 1 dt) (nth 2 dt)))) + (let ((date (math-absolute-from-dt (car dt) (nth 1 dt) (nth 2 dt)))) + (if (nth 3 dt) + (math-add (math-float date) + (math-div (math-add (+ (* (nth 3 dt) 3600) + (* (nth 4 dt) 60)) + (nth 5 dt)) + '(float 864 2))) + date))) + +(defun math-iso-dt-to-date (dt) + (let ((date (math-absolute-from-iso-dt (car dt) (nth 1 dt) (nth 2 dt)))) (if (nth 3 dt) (math-add (math-float date) (math-div (math-add (+ (* (nth 3 dt) 3600) @@ -446,11 +519,17 @@ (defun math-this-year () (nth 5 (decode-time))) -(defun math-leap-year-p (year) - (if (Math-lessp year 1752) +(defun math-leap-year-p (year &optional julian) + "Non-nil if YEAR is a leap year. +If JULIAN is non-nil, then use the criterion for leap years +in the Julian calendar, otherwise use the criterion in the +Gregorian calendar." + (if julian (if (math-negp year) (= (math-imod (math-neg year) 4) 1) (= (math-imod year 4) 0)) + (if (math-negp year) + (setq year (math-sub -1 year))) (setq year (math-imod year 400)) (or (and (= (% year 4) 0) (/= (% year 100) 0)) (= year 0)))) @@ -460,39 +539,112 @@ 29 (aref [31 28 31 30 31 30 31 31 30 31 30 31] (1- month)))) -(defun math-day-number (year month day) +(defun math-day-in-year (year month day &optional julian) + "Return the number of days of the year up to YEAR MONTH DAY. +The count includes the given date. +If JULIAN is non-nil, use the Julian calendar, otherwise +use the Gregorian calendar." (let ((day-of-year (+ day (* 31 (1- month))))) (if (> month 2) (progn (setq day-of-year (- day-of-year (/ (+ 23 (* 4 month)) 10))) - (if (math-leap-year-p year) + (if (math-leap-year-p year julian) (setq day-of-year (1+ day-of-year))))) - (and (eq year 1752) - (or (> month 9) - (and (= month 9) (>= day 14))) - (setq day-of-year (- day-of-year 11))) day-of-year)) -(defun math-absolute-from-date (year month day) +(defun math-day-number (year month day) + "Return the number of days of the year up to YEAR MONTH DAY. +The count includes the given date." + (if calc-gregorian-switch + (cond ((eq year (nth 0 calc-gregorian-switch)) + (1+ + (- (math-absolute-from-dt year month day) + (math-absolute-from-dt year 1 1)))) + ((Math-lessp year (nth 0 calc-gregorian-switch)) + (math-day-in-year year month day t)) + (t + (math-day-in-year year month day))) + (math-day-in-year year month day))) + +(defun math-dt-before-p (dt1 dt2) + "Non-nil if DT1 occurs before DT2. +A DT is a list of the form (YEAR MONTH DAY)." + (or (Math-lessp (nth 0 dt1) (nth 0 dt2)) + (and (equal (nth 0 dt1) (nth 0 dt2)) + (or (< (nth 1 dt1) (nth 1 dt2)) + (and (= (nth 1 dt1) (nth 1 dt2)) + (< (nth 2 dt1) (nth 2 dt2))))))) + +(defun math-absolute-from-gregorian-dt (year month day) + "Return the DATE of the day given by the Gregorian day YEAR MONTH DAY. +Recall that DATE is the number of days since December 31, -1 +in the Gregorian calendar." (if (eq year 0) (setq year -1)) (let ((yearm1 (math-sub year 1))) - (math-sub (math-add (math-day-number year month day) - (math-add (math-mul 365 yearm1) - (if (math-posp year) - (math-quotient yearm1 4) - (math-sub 365 - (math-quotient (math-sub 3 year) - 4))))) - (if (or (Math-lessp year 1753) - (and (eq year 1752) (<= month 9))) - 1 - (let ((correction (math-mul (math-quotient yearm1 100) 3))) - (let ((res (math-idivmod correction 4))) - (math-add (if (= (cdr res) 0) - -1 - 0) - (car res)))))))) - + (math-sub + ;; Add the number of days of the year and the numbers of days + ;; in the previous years (leap year days to be added separately) + (math-add (math-day-in-year year month day) + (math-add (math-mul 365 yearm1) + ;; Add the number of Julian leap years + (if (math-posp year) + (math-quotient yearm1 4) + (math-sub 365 + (math-quotient (math-sub 3 year) + 4))))) + ;; Subtract the number of Julian leap years which are not + ;; Gregorian leap years. In C=4N+r centuries, there will + ;; be 3N+r of these days. The following will compute + ;; 3N+r. + (let* ((correction (math-mul (math-quotient yearm1 100) 3)) + (res (math-idivmod correction 4))) + (math-add (if (= (cdr res) 0) + 0 + 1) + (car res)))))) + +(defun math-absolute-from-julian-dt (year month day) + "Return the DATE of the day given by the Julian day YEAR MONTH DAY. +Recall that DATE is the number of days since December 31, -1 +in the Gregorian calendar." + (if (eq year 0) (setq year -1)) + (let ((yearm1 (math-sub year 1))) + (math-sub + ;; Add the number of days of the year and the numbers of days + ;; in the previous years (leap year days to be added separately) + (math-add (math-day-in-year year month day) + (math-add (math-mul 365 yearm1) + ;; Add the number of Julian leap years + (if (math-posp year) + (math-quotient yearm1 4) + (math-sub 365 + (math-quotient (math-sub 3 year) + 4))))) + ;; Adjustment, since January 1, 1 (Julian) is absolute day -1 + 2))) + +;; calc-gregorian-switch is a customizable variable defined in calc.el +(defvar calc-gregorian-switch) + +(defun math-absolute-from-iso-dt (year week day) + "Return the DATE of the day given by the iso8601 day YEAR WEEK DAY." + (let* ((janfour (math-absolute-from-gregorian-dt year 1 4)) + (prevmon (math-sub janfour + (cdr (math-idivmod (math-sub janfour 1) 7))))) + (math-add + (math-add prevmon (* (1- week) 7)) + (if (zerop day) 6 (1- day))))) + +(defun math-absolute-from-dt (year month day) + "Return the DATE of the day given by the day YEAR MONTH DAY. +Recall that DATE is the number of days since December 31, -1 +in the Gregorian calendar." + (if (and calc-gregorian-switch + ;; The next few lines determine if the given date + ;; occurs before the switch to the Gregorian calendar. + (math-dt-before-p (list year month day) calc-gregorian-switch)) + (math-absolute-from-julian-dt year month day) + (math-absolute-from-gregorian-dt year month day))) ;;; It is safe to redefine these in your init file to use a different ;;; language. @@ -526,6 +678,10 @@ (defvar math-fd-minute) (defvar math-fd-second) (defvar math-fd-bc-flag) +(defvar math-fd-iso-dt) +(defvar math-fd-isoyear) +(defvar math-fd-isoweek) +(defvar math-fd-isoweekday) (defun math-format-date (math-fd-date) (if (eq (car-safe math-fd-date) 'date) @@ -533,12 +689,14 @@ (let ((entry (list math-fd-date calc-internal-prec calc-date-format))) (or (cdr (assoc entry math-format-date-cache)) (let* ((math-fd-dt nil) + (math-fd-iso-dt nil) (calc-group-digits nil) (calc-leading-zeros nil) (calc-number-radix 10) (calc-twos-complement-mode nil) math-fd-year math-fd-month math-fd-day math-fd-weekday math-fd-hour math-fd-minute math-fd-second + math-fd-isoyear math-fd-isoweek math-fd-isoweekday (math-fd-bc-flag nil) (fmt (apply 'concat (mapcar 'math-format-date-part calc-date-format)))) @@ -548,13 +706,13 @@ (setcdr math-fd-dt nil)) fmt)))) -(defconst math-julian-date-beginning '(float 17214235 -1) - "The beginning of the Julian calendar, -as measured in the number of days before January 1 of the year 1AD.") +(defconst math-julian-date-beginning '(float 17214225 -1) + "The beginning of the Julian date calendar, +as measured in the number of days before December 31, 1 BC (Gregorian).") -(defconst math-julian-date-beginning-int 1721424 - "The beginning of the Julian calendar, -as measured in the integer number of days before January 1 of the year 1AD.") +(defconst math-julian-date-beginning-int 1721423 + "The beginning of the Julian date calendar, +as measured in the integer number of days before December 31, 1 BC (Gregorian).") (defun math-format-date-part (x) (cond ((stringp x) @@ -578,6 +736,23 @@ as measured in the integer number of days before January 1 of the year 1AD.") math-julian-date-beginning-int))) ((eq x 'U) (math-format-number (nth 1 (math-date-parts math-fd-date 719164)))) + ((memq x '(IYYY Iww w)) + (progn + (or math-fd-iso-dt + (setq math-fd-iso-dt (math-date-to-iso-dt math-fd-date) + math-fd-isoyear (car math-fd-iso-dt) + math-fd-isoweek (nth 1 math-fd-iso-dt) + math-fd-isoweekday (nth 2 math-fd-iso-dt))) + (cond ((eq x 'IYYY) + (let* ((neg (Math-negp math-fd-isoyear)) + (pyear (calcFunc-abs math-fd-isoyear))) + (if (and (natnump pyear) (< pyear 10000)) + (concat (if neg "-" "") (format "%04d" pyear)) + (concat (if neg "-" "+") (math-format-number pyear))))) + ((eq x 'Iww) + (concat "W" (format "%02d" math-fd-isoweek))) + ((eq x 'w) + (format "%d" math-fd-isoweekday))))) ((progn (or math-fd-dt (progn @@ -585,8 +760,7 @@ as measured in the integer number of days before January 1 of the year 1AD.") math-fd-year (car math-fd-dt) math-fd-month (nth 1 math-fd-dt) math-fd-day (nth 2 math-fd-dt) - math-fd-weekday (math-mod - (math-add (math-floor math-fd-date) 6) 7) + math-fd-weekday (math-mod (math-floor math-fd-date) 7) math-fd-hour (nth 3 math-fd-dt) math-fd-minute (nth 4 math-fd-dt) math-fd-second (nth 5 math-fd-dt)) @@ -609,6 +783,15 @@ as measured in the integer number of days before January 1 of the year 1AD.") (if (and (natnump math-fd-year) (< math-fd-year 100)) (format "+%d" math-fd-year) (math-format-number math-fd-year))) + ((eq x 'ZYYY) + (let* ((year (if (Math-negp math-fd-year) + (math-add math-fd-year 1) + math-fd-year)) + (neg (Math-negp year)) + (pyear (calcFunc-abs year))) + (if (and (natnump pyear) (< pyear 10000)) + (concat (if neg "-" "") (format "%04d" pyear)) + (concat (if neg "-" "+") (math-format-number pyear))))) ((eq x 'b) "") ((eq x 'aa) (and (not math-fd-bc-flag) "ad")) @@ -634,6 +817,7 @@ as measured in the integer number of days before January 1 of the year 1AD.") (and math-fd-bc-flag "b.c.")) ((eq x 'BBBB) (and math-fd-bc-flag "B.C.")) + ((eq x 'T) "T") ((eq x 'M) (format "%d" math-fd-month)) ((eq x 'MM) @@ -734,6 +918,8 @@ as measured in the integer number of days before January 1 of the year 1AD.") (catch 'syntax (or (math-parse-standard-date math-pd-str t) (math-parse-standard-date math-pd-str nil) + (and (string-match "W[0-9][0-9]" math-pd-str) + (math-parse-iso-date math-pd-str)) (and (string-match "\\`[^-+/0-9a-zA-Z]*\\([-+]?[0-9]+\\.?[0-9]*\\([eE][-+]?[0-9]+\\)?\\)[^-+/0-9a-zA-Z]*\\'" math-pd-str) (list 'date (math-read-number (math-match-substring math-pd-str 1)))) (let ((case-fold-search t) @@ -757,8 +943,12 @@ as measured in the integer number of days before January 1 of the year 1AD.") (setq second 0) (setq second (math-read-number second))) (if (equal ampm "") - (if (> hour 23) - (throw 'syntax "Hour value out of range")) + (if (or + (> hour 24) + (and (= hour 24) + (not (= minute 0)) + (not (eq second 0)))) + (throw 'syntax "Hour value is out of range")) (setq ampm (upcase (aref ampm 0))) (if (memq ampm '(?N ?M)) (if (and (= hour 12) (= minute 0) (eq second 0)) @@ -766,7 +956,7 @@ as measured in the integer number of days before January 1 of the year 1AD.") (throw 'syntax "Time must be 12:00:00 in this context")) (if (or (= hour 0) (> hour 12)) - (throw 'syntax "Hour value out of range")) + (throw 'syntax "Hour value is out of range")) (if (eq (= ampm ?A) (= hour 12)) (setq hour (% (+ hour 12) 24))))))) @@ -889,7 +1079,11 @@ as measured in the integer number of days before January 1 of the year 1AD.") (throw 'syntax "Day value is out of range")) (and hour (progn - (if (or (< hour 0) (> hour 23)) + (if (or (< hour 0) + (> hour 24) + (and (= hour 24) + (not (= minute 0)) + (not (eq second 0)))) (throw 'syntax "Hour value is out of range")) (if (or (< minute 0) (> minute 59)) (throw 'syntax "Minute value is out of range")) @@ -898,6 +1092,26 @@ as measured in the integer number of days before January 1 of the year 1AD.") (list 'date (math-dt-to-date (append (list year month day) (and hour (list hour minute second)))))) +(defun math-parse-iso-date-validate (isoyear isoweek isoweekday hour minute second) + (if (or (< isoweek 1) (> isoweek 53)) + (throw 'syntax "Week value is out of range")) + (if (or (< isoweekday 1) (> isoweekday 7)) + (throw 'syntax "Weekday value is out of range")) + (and hour + (progn + (if (or (< hour 0) + (> hour 24) + (and (= hour 24) + (not (= minute 0)) + (not (eq second 0)))) + (throw 'syntax "Hour value is out of range")) + (if (or (< minute 0) (> minute 59)) + (throw 'syntax "Minute value is out of range")) + (if (or (math-negp second) (not (Math-lessp second 60))) + (throw 'syntax "Seconds value is out of range")))) + (list 'date (math-iso-dt-to-date (append (list isoyear isoweek isoweekday) + (and hour (list hour minute second)))))) + (defun math-parse-date-word (names &optional front) (let ((n 1)) (while (and names (not (string-match (if (equal (car names) "Sep") @@ -918,6 +1132,7 @@ as measured in the integer number of days before January 1 of the year 1AD.") (let ((case-fold-search t) (okay t) num (fmt calc-date-format) this next (gnext nil) + (isoyear nil) (isoweek nil) (isoweekday nil) (year nil) (month nil) (day nil) (bigyear nil) (yearday nil) (hour nil) (minute nil) (second nil) (bc-flag nil)) (while (and fmt okay) @@ -994,19 +1209,35 @@ as measured in the integer number of days before January 1 of the year 1AD.") (if (string-match "\\`pm\\|p\\.m\\." math-pd-str) (setq hour (if (= hour 12) 12 (% (+ hour 12) 24)) math-pd-str (substring math-pd-str (match-end 0)))))) - ((memq this '(Y YY BY YYY YYYY)) + ((memq this '(Y YY BY YYY YYYY ZYYY)) (and (if (memq next '(MM DD ddd hh HH mm ss SS)) (if (memq this '(Y YY BYY)) (string-match "\\` *[0-9][0-9]" math-pd-str) (string-match "\\`[0-9][0-9][0-9][0-9]" math-pd-str)) (string-match "\\`[-+]?[0-9]+" math-pd-str)) (setq year (math-match-substring math-pd-str 0) - bigyear (or (eq this 'YYY) + bigyear (or (eq this 'YYY) (memq (aref math-pd-str 0) '(?\+ ?\-))) math-pd-str (substring math-pd-str (match-end 0)) - year (math-read-number year)))) + year (math-read-number year)) + (if (and (eq this 'ZYYY) (eq year 0)) + (setq year (math-sub year 1) + bigyear t) + t))) + ((eq this 'IYYY) + (if (string-match "\\`[-+]?[0-9]+" math-pd-str) + (setq isoyear (string-to-number (math-match-substring math-pd-str 0)) + math-pd-str (substring math-pd-str (match-end 0))))) + ((eq this 'Iww) + (if (string-match "W\\([0-9][0-9]\\)" math-pd-str) + (setq isoweek (string-to-number (math-match-substring math-pd-str 1)) + math-pd-str (substring math-pd-str 3)))) ((eq this 'b) t) + ((eq this 'T) + (if (eq (aref math-pd-str 0) ?T) + (setq math-pd-str (substring math-pd-str 1)) + t)) ((memq this '(aa AA aaaa AAAA)) (if (string-match "\\` *\\(ad\\|a\\.d\\.\\)" math-pd-str) (setq math-pd-str (substring math-pd-str (match-end 0))))) @@ -1041,7 +1272,9 @@ as measured in the integer number of days before January 1 of the year 1AD.") nil)) nil) ((eq this 'W) - (and (>= num 0) (< num 7))) + (and (>= num 0) (< num 7))) + ((eq this 'w) + (setq isoweekday num)) ((memq this '(d ddd bdd)) (setq yearday num)) ((memq this '(M MM BM)) @@ -1058,19 +1291,46 @@ as measured in the integer number of days before January 1 of the year 1AD.") (setq yearday nil) (setq month 1 day 1))) (if (and okay (equal math-pd-str "")) - (and month day (or (not (or hour minute second)) - (and hour minute)) - (progn - (or year (setq year (math-this-year))) - (or second (setq second 0)) - (if bc-flag - (setq year (math-neg (math-abs year)))) - (setq day (math-parse-date-validate year bigyear month day - hour minute second)) - (if yearday - (setq day (math-add day (1- yearday)))) - day))))) - + (if isoyear + (math-parse-iso-date-validate isoyear isoweek isoweekday hour minute second) + (and month day (or (not (or hour minute second)) + (and hour minute)) + (progn + (or year (setq year (math-this-year))) + (or second (setq second 0)) + (if bc-flag + (setq year (math-neg (math-abs year)))) + (setq day (math-parse-date-validate year bigyear month day + hour minute second)) + (if yearday + (setq day (math-add day (1- yearday)))) + day)))))) + +(defun math-parse-iso-date (math-pd-str) + "Parse MATH-PD-STR as an ISO week date, or return nil." + (let ((case-fold-search t) + (isoyear nil) (isoweek nil) (isoweekday nil) + (hour nil) (minute nil) (second nil)) + ;; Extract the time, if any. + (if (string-match "T[^0-9]*\\([0-9][0-9]\\)[^0-9]*\\([0-9][0-9]\\)?[^0-9]*\\([0-9][0-9]\\(\\.[0-9]+\\)?\\)?" math-pd-str) + (progn + (setq hour (string-to-number (math-match-substring math-pd-str 1)) + minute (math-match-substring math-pd-str 2) + second (math-match-substring math-pd-str 3) + math-pd-str (substring math-pd-str 0 (match-beginning 0))) + (if (equal minute "") + (setq minute 0) + (setq minute (string-to-number minute))) + (if (equal second "") + (setq second 0) + (setq second (math-read-number second))))) + ;; Next, the year, week and weekday + (if (string-match "\\(-?[0-9]*\\)[^0-9]*W\\([0-9][0-9]\\)[^0-9]*\\([0-9]\\)[^0-9]*\\'" math-pd-str) + (progn + (setq isoyear (string-to-number (math-match-substring math-pd-str 1)) + isoweek (string-to-number (math-match-substring math-pd-str 2)) + isoweekday (string-to-number (math-match-substring math-pd-str 3))) + (math-parse-iso-date-validate isoyear isoweek isoweekday hour minute second))))) (defun calcFunc-now (&optional zone) (let ((date (let ((calc-date-format nil)) @@ -1098,7 +1358,7 @@ as measured in the integer number of days before January 1 of the year 1AD.") (setq date (nth 1 date))) (or (math-realp date) (math-reject-arg date 'datep)) - (math-mod (math-add (math-floor date) 6) 7)) + (math-mod (math-floor date) 7)) (defun calcFunc-yearday (date) (let ((dt (math-date-to-dt date))) @@ -1298,7 +1558,7 @@ second, the number of seconds offset for daylight savings." 0))) (rounded-abs-date (+ - (calendar-absolute-from-gregorian + (calendar-absolute-from-gregorian (list (nth 1 dt) (nth 2 dt) (nth 0 dt))) (/ (round (* 60 time)) 60.0 24.0)))) (if (dst-in-effect rounded-abs-date) @@ -1434,28 +1694,100 @@ and ends on the last Sunday of October at 2 a.m." (and (math-messy-integerp day) (setq day (math-trunc day))) (or (integerp day) (math-reject-arg day 'fixnump)) (and (or (< day 0) (> day 31)) (math-reject-arg day 'range)) - (let ((dt (math-date-to-dt date))) - (if (or (= day 0) (> day (math-days-in-month (car dt) (nth 1 dt)))) - (setq day (math-days-in-month (car dt) (nth 1 dt)))) - (and (eq (car dt) 1752) (= (nth 1 dt) 9) - (if (>= day 14) (setq day (- day 11)))) - (list 'date (math-add (math-dt-to-date (list (car dt) (nth 1 dt) 1)) - (1- day))))) + (let* ((dt (math-date-to-dt date)) + (dim (math-days-in-month (car dt) (nth 1 dt))) + (julian (if calc-gregorian-switch + (math-date-to-dt (math-sub + (or (nth 3 calc-gregorian-switch) + (apply 'math-absolute-from-gregorian-dt calc-gregorian-switch)) + 1))))) + (if (or (= day 0) (> day dim)) + (setq day (1- dim)) + (setq day (1- day))) + ;; Adjust if this occurs near the switch to the Gregorian calendar + (if calc-gregorian-switch + (cond + ((and (math-dt-before-p (list (car dt) (nth 1 dt) 1) calc-gregorian-switch) + (math-dt-before-p julian (list (car dt) (nth 1 dt) 1))) + ;; In this case, CALC-GREGORIAN-SWITCH is the first day of the month + (list 'date + (math-dt-to-date (list (car calc-gregorian-switch) + (nth 1 calc-gregorian-switch) + (if (> (+ (nth 2 calc-gregorian-switch) day) dim) + dim + (+ (nth 2 calc-gregorian-switch) day)))))) + ((and (eq (car dt) (car calc-gregorian-switch)) + (= (nth 1 dt) (nth 1 calc-gregorian-switch))) + ;; In this case, the switch to the Gregorian calendar occurs in the given month + (if (< (+ (nth 2 julian) day) (nth 2 calc-gregorian-switch)) + ;; If the DAYth day occurs before the switch, use it + (list 'date (math-dt-to-date (list (car dt) (nth 1 dt) (1+ day)))) + ;; Otherwise do some computations + (let ((tm (+ day (- (nth 2 calc-gregorian-switch) (nth 2 julian))))) + (list 'date (math-dt-to-date + (list (car dt) + (nth 1 dt) + ;; + (if (> tm dim) dim tm))))))) + ((and (eq (car dt) (car julian)) + (= (nth 1 dt) (nth 1 julian))) + ;; In this case, the current month is truncated because of the switch + ;; to the Gregorian calendar + (list 'date (math-dt-to-date + (list (car dt) + (nth 1 dt) + (if (>= day (nth 2 julian)) + (nth 2 julian) + (1+ day)))))) + (t + ;; The default + (list 'date (math-add (math-dt-to-date (list (car dt) (nth 1 dt) 1)) day)))) + (list 'date (math-add (math-dt-to-date (list (car dt) (nth 1 dt) 1)) day))))) (defun calcFunc-newyear (date &optional day) + (if (eq (car-safe date) 'date) (setq date (nth 1 date))) (or day (setq day 1)) (and (math-messy-integerp day) (setq day (math-trunc day))) (or (integerp day) (math-reject-arg day 'fixnump)) - (let ((dt (math-date-to-dt date))) + (let* ((dt (math-date-to-dt date)) + (gregbeg (if calc-gregorian-switch + (or (nth 3 calc-gregorian-switch) + (apply 'math-absolute-from-gregorian-dt calc-gregorian-switch)))) + (julianend (if calc-gregorian-switch (math-sub gregbeg 1))) + (julian (if calc-gregorian-switch + (math-date-to-dt julianend)))) (if (and (>= day 0) (<= day 366)) - (let ((max (if (eq (car dt) 1752) 355 - (if (math-leap-year-p (car dt)) 366 365)))) + (let ((max (if (math-leap-year-p (car dt)) 366 365))) (if (or (= day 0) (> day max)) (setq day max)) - (list 'date (math-add (math-dt-to-date (list (car dt) 1 1)) - (1- day)))) + (if calc-gregorian-switch + ;; Now to break this down into cases + (cond + ((and (math-dt-before-p (list (car dt) 1 1) calc-gregorian-switch) + (math-dt-before-p julian (list (car dt) 1 1))) + ;; In this case, CALC-GREGORIAN-SWITCH is the first day of the year + (list 'date (math-min (math-add gregbeg (1- day)) + (math-dt-to-date (list (car calc-gregorian-switch) 12 31))))) + ((eq (car dt) (car julian)) + ;; In this case, the switch to the Gregorian calendar occurs in the given year + (if (Math-lessp (car julian) (car calc-gregorian-switch)) + ;; Here, the last Julian day is the last day of the year. + (list 'date (math-min (math-add (math-dt-to-date (list (car dt) 1 1)) (1- day)) + julianend)) + ;; Otherwise, just make sure the date doesn't go past the end of the year + (list 'date (math-min (math-add (math-dt-to-date (list (car dt) 1 1)) (1- day)) + (math-dt-to-date (list (car dt) 12 31)))))) + (t + (list 'date (math-add (math-dt-to-date (list (car dt) 1 1)) + (1- day))))) + (list 'date (math-add (math-dt-to-date (list (car dt) 1 1)) + (1- day))))) (if (and (>= day -12) (<= day -1)) - (list 'date (math-dt-to-date (list (car dt) (- day) 1))) - (math-reject-arg day 'range))))) + (if (and calc-gregorian-switch + (math-dt-before-p (list (car dt) (- day) 1) calc-gregorian-switch) + (math-dt-before-p julian (list (car dt) (- day) 1))) + (list 'date gregbeg) + (list 'date (math-dt-to-date (list (car dt) (- day) 1)))) + (math-reject-arg day 'range))))) (defun calcFunc-incmonth (date &optional step) (or step (setq step 1)) diff --git a/lisp/calc/calc-graph.el b/lisp/calc/calc-graph.el index 4376e21b4ca..c84c7fdf949 100644 --- a/lisp/calc/calc-graph.el +++ b/lisp/calc/calc-graph.el @@ -948,6 +948,7 @@ This \"dumb\" driver will be present in Gnuplot 3.0." (setq calc-dumb-map (make-sparse-keymap)) (define-key calc-dumb-map "\n" 'scroll-up-command) (define-key calc-dumb-map " " 'scroll-up-command) + (define-key calc-dump-map [?\S-\ ] 'scroll-down-command) (define-key calc-dumb-map "\177" 'scroll-down-command) (define-key calc-dumb-map "<" 'scroll-left) (define-key calc-dumb-map ">" 'scroll-right) diff --git a/lisp/calc/calc-help.el b/lisp/calc/calc-help.el index 512faefa78f..2b7b56c3f89 100644 --- a/lisp/calc/calc-help.el +++ b/lisp/calc/calc-help.el @@ -386,23 +386,9 @@ C-w Describe how there is no warranty for Calc." (defun calc-view-news () (interactive) - (let ((path load-path)) - (while (and path - (not (file-exists-p (expand-file-name "calc.el" (car path))))) - (setq path (cdr path))) - (or (and path - (file-exists-p (expand-file-name "README" (car path)))) - (error "Can't locate Calc sources")) - (calc-quit) - (switch-to-buffer "*Help*") - (let ((inhibit-read-only t)) - (erase-buffer) - (insert-file-contents (expand-file-name "README" (car path))) - (search-forward "Summary of changes") - (forward-line -1) - (delete-region (point-min) (point)) - (goto-char (point-min))) - (help-mode))) + (calc-quit) + (view-emacs-news) + (re-search-forward "^\*+ .*\\<Calc\\>" nil t)) (defvar calc-help-long-names '((?b . "binary/business") (?g . "graphics") diff --git a/lisp/calc/calc-units.el b/lisp/calc/calc-units.el index a3d037ee042..b334d7b3b45 100644 --- a/lisp/calc/calc-units.el +++ b/lisp/calc/calc-units.el @@ -404,7 +404,7 @@ If EXPR is nil, return nil." (math-composition-to-string cexpr)))))) (defvar math-default-units-table - #s(hash-table test equal data (1 (1))) + (make-hash-table :test 'equal) "A table storing previously converted units.") (defun math-get-default-units (expr) @@ -437,20 +437,32 @@ If COMP or STD is non-nil, put that in the units table instead." (list new-units (car default-units)) math-default-units-table)))))) +(defvar calc-allow-units-as-numbers) + (defun calc-convert-units (&optional old-units new-units) (interactive) (calc-slow-wrapper (let ((expr (calc-top-n 1)) (uoldname nil) + (unitscancel nil) + (nouold nil) unew units defunits) - (unless (math-units-in-expr-p expr t) + (if (or (not (math-units-in-expr-p expr t)) + (setq unitscancel (and + calc-allow-units-as-numbers + (eq (math-get-standard-units expr) 1)))) (let ((uold (or old-units (progn - (setq uoldname (read-string "Old units: ")) + (setq uoldname + (if unitscancel + (read-string + "(The expression is unitless when simplified) Old Units: ") + (read-string "Old units: "))) (if (equal uoldname "") (progn + (setq nouold unitscancel) (setq uoldname "1") 1) (if (string-match "\\` */" uoldname) @@ -460,47 +472,43 @@ If COMP or STD is non-nil, put that in the units table instead." (error "Bad format in units expression: %s" (nth 1 uold))) (setq expr (math-mul expr uold)))) (setq defunits (math-get-default-units expr)) - (if (equal defunits "1") - (progn - (calc-enter-result 1 "cvun" (math-simplify-units expr)) - (message "All units in expression cancel")) - (unless new-units - (setq new-units - (read-string (concat - (if uoldname - (concat "Old units: " - uoldname - ", new units") - "New units") - (if defunits - (concat - " (default " - defunits - "): ") - ": ")))) - (if (and - (string= new-units "") - defunits) - (setq new-units defunits))) - (when (string-match "\\` */" new-units) - (setq new-units (concat "1" new-units))) - (setq units (math-read-expr new-units)) - (when (eq (car-safe units) 'error) - (error "Bad format in units expression: %s" (nth 2 units))) - (if calc-ensure-consistent-units - (math-check-unit-consistency expr units)) - (let ((unew (math-units-in-expr-p units t)) - (std (and (eq (car-safe units) 'var) - (assq (nth 1 units) math-standard-units-systems))) - (comp (eq (car-safe units) '+))) - (unless (or unew std) - (error "No units specified")) - (let ((res - (if std - (math-simplify-units (math-to-standard-units expr (nth 1 std))) - (math-convert-units expr units (and uoldname (not (equal uoldname "1"))))))) - (math-put-default-units res (if comp units)) - (calc-enter-result 1 "cvun" res))))))) + (unless new-units + (setq new-units + (read-string (concat + (if (and uoldname (not nouold)) + (concat "Old units: " + uoldname + ", new units") + "New units") + (if defunits + (concat + " (default " + defunits + "): ") + ": ")))) + (if (and + (string= new-units "") + defunits) + (setq new-units defunits))) + (when (string-match "\\` */" new-units) + (setq new-units (concat "1" new-units))) + (setq units (math-read-expr new-units)) + (when (eq (car-safe units) 'error) + (error "Bad format in units expression: %s" (nth 2 units))) + (if calc-ensure-consistent-units + (math-check-unit-consistency expr units)) + (let ((unew (math-units-in-expr-p units t)) + (std (and (eq (car-safe units) 'var) + (assq (nth 1 units) math-standard-units-systems))) + (comp (eq (car-safe units) '+))) + (unless (or unew std) + (error "No units specified")) + (let ((res + (if std + (math-simplify-units (math-to-standard-units expr (nth 1 std))) + (math-convert-units expr units (and uoldname (not (equal uoldname "1"))))))) + (math-put-default-units res (if comp units)) + (calc-enter-result 1 "cvun" res)))))) (defun calc-autorange-units (arg) (interactive "P") diff --git a/lisp/calc/calc.el b/lisp/calc/calc.el index ddba0fecfea..db30d53d537 100644 --- a/lisp/calc/calc.el +++ b/lisp/calc/calc.el @@ -426,6 +426,14 @@ when converting units." :version "24.3" :type 'boolean) +(defcustom calc-allow-units-as-numbers + t + "If non-nil, allow unit expressions to be treated like numbers +when converting units, if the expression can be simplified to be unitless." + :group 'calc + :version "24.4" + :type 'boolean) + (defcustom calc-undo-length 100 "The number of undo steps that will be preserved when Calc is quit." @@ -435,9 +443,9 @@ when converting units." (defcustom calc-highlight-selections-with-faces nil "If non-nil, use a separate face to indicate selected sub-formulas. -If `calc-show-selections' is non-nil, then selected sub-formulas are shown -by displaying the rest of the formula in `calc-nonselected-face'. -If `calc-show-selections' is nil, then selected sub-formulas are shown +If option `calc-show-selections' is non-nil, then selected sub-formulas are +shown by displaying the rest of the formula in `calc-nonselected-face'. +If option `calc-show-selections' is nil, then selected sub-formulas are shown by displaying the sub-formula in `calc-selected-face'." :version "24.1" :group 'calc @@ -464,6 +472,8 @@ to be identified as that note." :type 'string :group 'calc) +(defvar math-format-date-cache) ; calc-forms.el + (defface calc-nonselected-face '((t :inherit shadow :slant italic)) @@ -785,7 +795,9 @@ If nil, selections displayed but ignored.") "M-D-Y< H:mm:SSpp>" "D-M-Y< h:mm:SS>" "j<, h:mm:SS>" - "YYddd< hh:mm:ss>")) + "YYddd< hh:mm:ss>" + "ZYYY-MM-DD Www< hh:mm>" + "IYYY-Iww-w<Thh:mm:ss>")) (defcalcmodevar calc-autorange-units nil "If non-nil, automatically set unit prefixes to keep units in a reasonable range.") @@ -1179,7 +1191,7 @@ Used by `calc-user-invocation'.") ;;;###autoload (defun calc-dispatch (&optional arg) - "Invoke the GNU Emacs Calculator. See `calc-dispatch-help' for details." + "Invoke the GNU Emacs Calculator. See \\[calc-dispatch-help] for details." (interactive "P") ; (sit-for echo-keystrokes) (condition-case err ; look for other keys bound to calc-dispatch @@ -2020,6 +2032,50 @@ See calc-keypad for details." (calc-refresh align))) (setq calc-refresh-count (1+ calc-refresh-count))) +;; Dates that are built-in options for `calc-gregorian-switch' should be +;; (YEAR MONTH DAY math-date-from-gregorian-dt(YEAR MONTH DAY)) for speed. +(defcustom calc-gregorian-switch nil + "The first day the Gregorian calendar is used by Calc's date forms. +This is `nil' (the default) if the Gregorian calendar is the only one used. +Otherwise, it should be a list `(YEAR MONTH DAY)' when Calc begins to use +the Gregorian calendar; Calc will use the Julian calendar for earlier dates. +The dates in which different regions of the world began to use the +Gregorian calendar vary quite a bit, even within a single country. +If you want Calc's date forms to switch between the Julian and +Gregorian calendar, you can specify the date or choose from several +common choices. Some of these choices should be taken with a grain +of salt; for example different parts of France changed calendars at +different times, and Sweden's change to the Gregorian calendar was +complicated. Also, the boundaries of the countries were different at +the times of the calendar changes than they are now. +The Vatican decided that the Gregorian calendar should take effect +on 15 October 1582 (Gregorian), and many Catholic countries made +the change then. Great Britain and its colonies had the Gregorian +calendar take effect on 14 September 1752 (Gregorian); this includes +the United States." + :group 'calc + :version "24.4" + :type '(choice (const :tag "Always use the Gregorian calendar" nil) + (const :tag "1582-10-15 - Italy, Poland, Portugal, Spain" (1582 10 15 577736)) + (const :tag "1582-12-20 - France" (1582 12 20 577802)) + (const :tag "1582-12-25 - Luxemburg" (1582 12 25 577807)) + (const :tag "1584-01-17 - Bohemia and Moravia" (1584 1 17 578195)) + (const :tag "1587-11-01 - Hungary" (1587 11 1 579579)) + (const :tag "1700-03-01 - Denmark" (1700 3 1 620607)) + (const :tag "1701-01-12 - Protestant Switzerland" (1701 1 12 620924)) + (const :tag "1752-09-14 - Great Britain and dominions" (1752 9 14 639797)) + (const :tag "1753-03-01 - Sweden" (1753 3 1 639965)) + (const :tag "1918-02-14 - Russia" (1918 2 14 700214)) + (const :tag "1919-04-14 - Romania" (1919 4 14 700638)) + (list :tag "(YEAR MONTH DAY)" + (integer :tag "Year") + (integer :tag "Month (integer)") + (integer :tag "Day"))) + :set (lambda (symbol value) + (set-default symbol value) + (setq math-format-date-cache nil) + (calc-refresh))) + ;;;; The Calc Trail buffer. (defun calc-check-trail-aligned () |