├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── derivative.pdf ├── derivative.sty └── derivative.tex /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .editorconfig 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The LaTeX Project Public License 2 | =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 3 | 4 | LPPL Version 1.3c 2008-05-04 5 | 6 | Copyright 1999 2002-2008 LaTeX3 Project 7 | Everyone is allowed to distribute verbatim copies of this 8 | license document, but modification of it is not allowed. 9 | 10 | 11 | PREAMBLE 12 | ======== 13 | 14 | The LaTeX Project Public License (LPPL) is the primary license under 15 | which the LaTeX kernel and the base LaTeX packages are distributed. 16 | 17 | You may use this license for any work of which you hold the copyright 18 | and which you wish to distribute. This license may be particularly 19 | suitable if your work is TeX-related (such as a LaTeX package), but 20 | it is written in such a way that you can use it even if your work is 21 | unrelated to TeX. 22 | 23 | The section `WHETHER AND HOW TO DISTRIBUTE WORKS UNDER THIS LICENSE', 24 | below, gives instructions, examples, and recommendations for authors 25 | who are considering distributing their works under this license. 26 | 27 | This license gives conditions under which a work may be distributed 28 | and modified, as well as conditions under which modified versions of 29 | that work may be distributed. 30 | 31 | We, the LaTeX3 Project, believe that the conditions below give you 32 | the freedom to make and distribute modified versions of your work 33 | that conform with whatever technical specifications you wish while 34 | maintaining the availability, integrity, and reliability of 35 | that work. If you do not see how to achieve your goal while 36 | meeting these conditions, then read the document `cfgguide.tex' 37 | and `modguide.tex' in the base LaTeX distribution for suggestions. 38 | 39 | 40 | DEFINITIONS 41 | =========== 42 | 43 | In this license document the following terms are used: 44 | 45 | `Work' 46 | Any work being distributed under this License. 47 | 48 | `Derived Work' 49 | Any work that under any applicable law is derived from the Work. 50 | 51 | `Modification' 52 | Any procedure that produces a Derived Work under any applicable 53 | law -- for example, the production of a file containing an 54 | original file associated with the Work or a significant portion of 55 | such a file, either verbatim or with modifications and/or 56 | translated into another language. 57 | 58 | `Modify' 59 | To apply any procedure that produces a Derived Work under any 60 | applicable law. 61 | 62 | `Distribution' 63 | Making copies of the Work available from one person to another, in 64 | whole or in part. Distribution includes (but is not limited to) 65 | making any electronic components of the Work accessible by 66 | file transfer protocols such as FTP or HTTP or by shared file 67 | systems such as Sun's Network File System (NFS). 68 | 69 | `Compiled Work' 70 | A version of the Work that has been processed into a form where it 71 | is directly usable on a computer system. This processing may 72 | include using installation facilities provided by the Work, 73 | transformations of the Work, copying of components of the Work, or 74 | other activities. Note that modification of any installation 75 | facilities provided by the Work constitutes modification of the Work. 76 | 77 | `Current Maintainer' 78 | A person or persons nominated as such within the Work. If there is 79 | no such explicit nomination then it is the `Copyright Holder' under 80 | any applicable law. 81 | 82 | `Base Interpreter' 83 | A program or process that is normally needed for running or 84 | interpreting a part or the whole of the Work. 85 | 86 | A Base Interpreter may depend on external components but these 87 | are not considered part of the Base Interpreter provided that each 88 | external component clearly identifies itself whenever it is used 89 | interactively. Unless explicitly specified when applying the 90 | license to the Work, the only applicable Base Interpreter is a 91 | `LaTeX-Format' or in the case of files belonging to the 92 | `LaTeX-format' a program implementing the `TeX language'. 93 | 94 | 95 | 96 | CONDITIONS ON DISTRIBUTION AND MODIFICATION 97 | =========================================== 98 | 99 | 1. Activities other than distribution and/or modification of the Work 100 | are not covered by this license; they are outside its scope. In 101 | particular, the act of running the Work is not restricted and no 102 | requirements are made concerning any offers of support for the Work. 103 | 104 | 2. You may distribute a complete, unmodified copy of the Work as you 105 | received it. Distribution of only part of the Work is considered 106 | modification of the Work, and no right to distribute such a Derived 107 | Work may be assumed under the terms of this clause. 108 | 109 | 3. You may distribute a Compiled Work that has been generated from a 110 | complete, unmodified copy of the Work as distributed under Clause 2 111 | above, as long as that Compiled Work is distributed in such a way that 112 | the recipients may install the Compiled Work on their system exactly 113 | as it would have been installed if they generated a Compiled Work 114 | directly from the Work. 115 | 116 | 4. If you are the Current Maintainer of the Work, you may, without 117 | restriction, modify the Work, thus creating a Derived Work. You may 118 | also distribute the Derived Work without restriction, including 119 | Compiled Works generated from the Derived Work. Derived Works 120 | distributed in this manner by the Current Maintainer are considered to 121 | be updated versions of the Work. 122 | 123 | 5. If you are not the Current Maintainer of the Work, you may modify 124 | your copy of the Work, thus creating a Derived Work based on the Work, 125 | and compile this Derived Work, thus creating a Compiled Work based on 126 | the Derived Work. 127 | 128 | 6. If you are not the Current Maintainer of the Work, you may 129 | distribute a Derived Work provided the following conditions are met 130 | for every component of the Work unless that component clearly states 131 | in the copyright notice that it is exempt from that condition. Only 132 | the Current Maintainer is allowed to add such statements of exemption 133 | to a component of the Work. 134 | 135 | a. If a component of this Derived Work can be a direct replacement 136 | for a component of the Work when that component is used with the 137 | Base Interpreter, then, wherever this component of the Work 138 | identifies itself to the user when used interactively with that 139 | Base Interpreter, the replacement component of this Derived Work 140 | clearly and unambiguously identifies itself as a modified version 141 | of this component to the user when used interactively with that 142 | Base Interpreter. 143 | 144 | b. Every component of the Derived Work contains prominent notices 145 | detailing the nature of the changes to that component, or a 146 | prominent reference to another file that is distributed as part 147 | of the Derived Work and that contains a complete and accurate log 148 | of the changes. 149 | 150 | c. No information in the Derived Work implies that any persons, 151 | including (but not limited to) the authors of the original version 152 | of the Work, provide any support, including (but not limited to) 153 | the reporting and handling of errors, to recipients of the 154 | Derived Work unless those persons have stated explicitly that 155 | they do provide such support for the Derived Work. 156 | 157 | d. You distribute at least one of the following with the Derived Work: 158 | 159 | 1. A complete, unmodified copy of the Work; 160 | if your distribution of a modified component is made by 161 | offering access to copy the modified component from a 162 | designated place, then offering equivalent access to copy 163 | the Work from the same or some similar place meets this 164 | condition, even though third parties are not compelled to 165 | copy the Work along with the modified component; 166 | 167 | 2. Information that is sufficient to obtain a complete, 168 | unmodified copy of the Work. 169 | 170 | 7. If you are not the Current Maintainer of the Work, you may 171 | distribute a Compiled Work generated from a Derived Work, as long as 172 | the Derived Work is distributed to all recipients of the Compiled 173 | Work, and as long as the conditions of Clause 6, above, are met with 174 | regard to the Derived Work. 175 | 176 | 8. The conditions above are not intended to prohibit, and hence do not 177 | apply to, the modification, by any method, of any component so that it 178 | becomes identical to an updated version of that component of the Work as 179 | it is distributed by the Current Maintainer under Clause 4, above. 180 | 181 | 9. Distribution of the Work or any Derived Work in an alternative 182 | format, where the Work or that Derived Work (in whole or in part) is 183 | then produced by applying some process to that format, does not relax or 184 | nullify any sections of this license as they pertain to the results of 185 | applying that process. 186 | 187 | 10. a. A Derived Work may be distributed under a different license 188 | provided that license itself honors the conditions listed in 189 | Clause 6 above, in regard to the Work, though it does not have 190 | to honor the rest of the conditions in this license. 191 | 192 | b. If a Derived Work is distributed under a different license, that 193 | Derived Work must provide sufficient documentation as part of 194 | itself to allow each recipient of that Derived Work to honor the 195 | restrictions in Clause 6 above, concerning changes from the Work. 196 | 197 | 11. This license places no restrictions on works that are unrelated to 198 | the Work, nor does this license place any restrictions on aggregating 199 | such works with the Work by any means. 200 | 201 | 12. Nothing in this license is intended to, or may be used to, prevent 202 | complete compliance by all parties with all applicable laws. 203 | 204 | 205 | NO WARRANTY 206 | =========== 207 | 208 | There is no warranty for the Work. Except when otherwise stated in 209 | writing, the Copyright Holder provides the Work `as is', without 210 | warranty of any kind, either expressed or implied, including, but not 211 | limited to, the implied warranties of merchantability and fitness for a 212 | particular purpose. The entire risk as to the quality and performance 213 | of the Work is with you. Should the Work prove defective, you assume 214 | the cost of all necessary servicing, repair, or correction. 215 | 216 | In no event unless required by applicable law or agreed to in writing 217 | will The Copyright Holder, or any author named in the components of the 218 | Work, or any other party who may distribute and/or modify the Work as 219 | permitted above, be liable to you for damages, including any general, 220 | special, incidental or consequential damages arising out of any use of 221 | the Work or out of inability to use the Work (including, but not limited 222 | to, loss of data, data being rendered inaccurate, or losses sustained by 223 | anyone as a result of any failure of the Work to operate with any other 224 | programs), even if the Copyright Holder or said author or said other 225 | party has been advised of the possibility of such damages. 226 | 227 | 228 | MAINTENANCE OF THE WORK 229 | ======================= 230 | 231 | The Work has the status `author-maintained' if the Copyright Holder 232 | explicitly and prominently states near the primary copyright notice in 233 | the Work that the Work can only be maintained by the Copyright Holder 234 | or simply that it is `author-maintained'. 235 | 236 | The Work has the status `maintained' if there is a Current Maintainer 237 | who has indicated in the Work that they are willing to receive error 238 | reports for the Work (for example, by supplying a valid e-mail 239 | address). It is not required for the Current Maintainer to acknowledge 240 | or act upon these error reports. 241 | 242 | The Work changes from status `maintained' to `unmaintained' if there 243 | is no Current Maintainer, or the person stated to be Current 244 | Maintainer of the work cannot be reached through the indicated means 245 | of communication for a period of six months, and there are no other 246 | significant signs of active maintenance. 247 | 248 | You can become the Current Maintainer of the Work by agreement with 249 | any existing Current Maintainer to take over this role. 250 | 251 | If the Work is unmaintained, you can become the Current Maintainer of 252 | the Work through the following steps: 253 | 254 | 1. Make a reasonable attempt to trace the Current Maintainer (and 255 | the Copyright Holder, if the two differ) through the means of 256 | an Internet or similar search. 257 | 258 | 2. If this search is successful, then enquire whether the Work 259 | is still maintained. 260 | 261 | a. If it is being maintained, then ask the Current Maintainer 262 | to update their communication data within one month. 263 | 264 | b. If the search is unsuccessful or no action to resume active 265 | maintenance is taken by the Current Maintainer, then announce 266 | within the pertinent community your intention to take over 267 | maintenance. (If the Work is a LaTeX work, this could be 268 | done, for example, by posting to comp.text.tex.) 269 | 270 | 3a. If the Current Maintainer is reachable and agrees to pass 271 | maintenance of the Work to you, then this takes effect 272 | immediately upon announcement. 273 | 274 | b. If the Current Maintainer is not reachable and the Copyright 275 | Holder agrees that maintenance of the Work be passed to you, 276 | then this takes effect immediately upon announcement. 277 | 278 | 4. If you make an `intention announcement' as described in 2b. above 279 | and after three months your intention is challenged neither by 280 | the Current Maintainer nor by the Copyright Holder nor by other 281 | people, then you may arrange for the Work to be changed so as 282 | to name you as the (new) Current Maintainer. 283 | 284 | 5. If the previously unreachable Current Maintainer becomes 285 | reachable once more within three months of a change completed 286 | under the terms of 3b) or 4), then that Current Maintainer must 287 | become or remain the Current Maintainer upon request provided 288 | they then update their communication data within one month. 289 | 290 | A change in the Current Maintainer does not, of itself, alter the fact 291 | that the Work is distributed under the LPPL license. 292 | 293 | If you become the Current Maintainer of the Work, you should 294 | immediately provide, within the Work, a prominent and unambiguous 295 | statement of your status as Current Maintainer. You should also 296 | announce your new status to the same pertinent community as 297 | in 2b) above. 298 | 299 | 300 | WHETHER AND HOW TO DISTRIBUTE WORKS UNDER THIS LICENSE 301 | ====================================================== 302 | 303 | This section contains important instructions, examples, and 304 | recommendations for authors who are considering distributing their 305 | works under this license. These authors are addressed as `you' in 306 | this section. 307 | 308 | Choosing This License or Another License 309 | ---------------------------------------- 310 | 311 | If for any part of your work you want or need to use *distribution* 312 | conditions that differ significantly from those in this license, then 313 | do not refer to this license anywhere in your work but, instead, 314 | distribute your work under a different license. You may use the text 315 | of this license as a model for your own license, but your license 316 | should not refer to the LPPL or otherwise give the impression that 317 | your work is distributed under the LPPL. 318 | 319 | The document `modguide.tex' in the base LaTeX distribution explains 320 | the motivation behind the conditions of this license. It explains, 321 | for example, why distributing LaTeX under the GNU General Public 322 | License (GPL) was considered inappropriate. Even if your work is 323 | unrelated to LaTeX, the discussion in `modguide.tex' may still be 324 | relevant, and authors intending to distribute their works under any 325 | license are encouraged to read it. 326 | 327 | A Recommendation on Modification Without Distribution 328 | ----------------------------------------------------- 329 | 330 | It is wise never to modify a component of the Work, even for your own 331 | personal use, without also meeting the above conditions for 332 | distributing the modified component. While you might intend that such 333 | modifications will never be distributed, often this will happen by 334 | accident -- you may forget that you have modified that component; or 335 | it may not occur to you when allowing others to access the modified 336 | version that you are thus distributing it and violating the conditions 337 | of this license in ways that could have legal implications and, worse, 338 | cause problems for the community. It is therefore usually in your 339 | best interest to keep your copy of the Work identical with the public 340 | one. Many works provide ways to control the behavior of that work 341 | without altering any of its licensed components. 342 | 343 | How to Use This License 344 | ----------------------- 345 | 346 | To use this license, place in each of the components of your work both 347 | an explicit copyright notice including your name and the year the work 348 | was authored and/or last substantially modified. Include also a 349 | statement that the distribution and/or modification of that 350 | component is constrained by the conditions in this license. 351 | 352 | Here is an example of such a notice and statement: 353 | 354 | %% pig.dtx 355 | %% Copyright 2005 M. Y. Name 356 | % 357 | % This work may be distributed and/or modified under the 358 | % conditions of the LaTeX Project Public License, either version 1.3 359 | % of this license or (at your option) any later version. 360 | % The latest version of this license is in 361 | % http://www.latex-project.org/lppl.txt 362 | % and version 1.3 or later is part of all distributions of LaTeX 363 | % version 2005/12/01 or later. 364 | % 365 | % This work has the LPPL maintenance status `maintained'. 366 | % 367 | % The Current Maintainer of this work is M. Y. Name. 368 | % 369 | % This work consists of the files pig.dtx and pig.ins 370 | % and the derived file pig.sty. 371 | 372 | Given such a notice and statement in a file, the conditions 373 | given in this license document would apply, with the `Work' referring 374 | to the three files `pig.dtx', `pig.ins', and `pig.sty' (the last being 375 | generated from `pig.dtx' using `pig.ins'), the `Base Interpreter' 376 | referring to any `LaTeX-Format', and both `Copyright Holder' and 377 | `Current Maintainer' referring to the person `M. Y. Name'. 378 | 379 | If you do not want the Maintenance section of LPPL to apply to your 380 | Work, change `maintained' above into `author-maintained'. 381 | However, we recommend that you use `maintained', as the Maintenance 382 | section was added in order to ensure that your Work remains useful to 383 | the community even when you can no longer maintain and support it 384 | yourself. 385 | 386 | Derived Works That Are Not Replacements 387 | --------------------------------------- 388 | 389 | Several clauses of the LPPL specify means to provide reliability and 390 | stability for the user community. They therefore concern themselves 391 | with the case that a Derived Work is intended to be used as a 392 | (compatible or incompatible) replacement of the original Work. If 393 | this is not the case (e.g., if a few lines of code are reused for a 394 | completely different task), then clauses 6b and 6d shall not apply. 395 | 396 | 397 | Important Recommendations 398 | ------------------------- 399 | 400 | Defining What Constitutes the Work 401 | 402 | The LPPL requires that distributions of the Work contain all the 403 | files of the Work. It is therefore important that you provide a 404 | way for the licensee to determine which files constitute the Work. 405 | This could, for example, be achieved by explicitly listing all the 406 | files of the Work near the copyright notice of each file or by 407 | using a line such as: 408 | 409 | % This work consists of all files listed in manifest.txt. 410 | 411 | in that place. In the absence of an unequivocal list it might be 412 | impossible for the licensee to determine what is considered by you 413 | to comprise the Work and, in such a case, the licensee would be 414 | entitled to make reasonable conjectures as to which files comprise 415 | the Work. 416 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## README for derivative package v1.4 dated 2024-02-08 2 | 3 | The package provides a set of commands `\NewDerivative`, `\NewDifferential` etc. that can be used to define a derivative or a differential operator, respectively. The package have already defined several derivatives and differentials: 4 | 5 | - `\odv` Ordinary derivative 6 | - `\pdv` Partial derivative 7 | - `\fdv` Functional derivative 8 | - `\mdv` Material derivative 9 | - `\adv` Average rate of change 10 | - `\jdv` Jacobian 11 | - `\odif` Shorthand for ordinary derivative 12 | - `\pdif` Shorthand for partial derivative 13 | - `\fdif` Shorthand for functional derivative 14 | - `\mdif` Shorthand for material derivative or general differential operator 15 | - `\adif` Difference 16 | 17 | ### Copyright and license 18 | 19 | Copyright 2019-2024 Simon Jensen 20 | 21 | This work may be distributed and/or modified under the 22 | conditions of the LaTeX Project Public License, either version 1.3 23 | of this license or (at your option) any later version. 24 | The latest version of this license is in 25 | http://www.latex-project.org/lppl.txt 26 | and version 1.3 or later is part of all distributions of LaTeX 27 | version 2005/12/01 or later. 28 | 29 | This work has the LPPL maintenance status `maintained`. 30 | 31 | The Current Maintainer of this work is Simon Jensen. 32 | Contributors: Romain Noel 33 | 34 | The bundle contains the files: 35 | 36 | README.md This file. 37 | derivative.sty The package itself. 38 | derivative.pdf The package documentation in PDF format. 39 | derivative.tex The master file that produced derivative.pdf. -------------------------------------------------------------------------------- /derivative.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sjelatex/derivative/f79685dd6d810d0d4319675db694c0b167a8511d/derivative.pdf -------------------------------------------------------------------------------- /derivative.sty: -------------------------------------------------------------------------------- 1 | % derivative.sty 2 | % Copyright 2019-2024 Simon Jensen 3 | % 4 | % This work may be distributed and/or modified under the 5 | % conditions of the LaTeX Project Public License, either version 1.3 6 | % of this license or (at your option) any later version. 7 | % The latest version of this license is in 8 | % http://www.latex-project.org/lppl.txt 9 | % and version 1.3 or later is part of all distributions of LaTeX 10 | % version 2005/12/01 or later. 11 | % 12 | % This work has the LPPL maintenance status `maintained'. 13 | % 14 | % The Current Maintainer of this work is Simon Jensen. 15 | % Contributors: Romain Noel 16 | 17 | \NeedsTeXFormat{LaTeX2e} 18 | 19 | \RequirePackage{expl3}[2023/12/08] 20 | \RequirePackage{l3keys2e} 21 | \ProvidesExplPackage{derivative}{2024/02/08}{1.4}{Nice and easy derivatives and differentials for LaTeX} 22 | 23 | \bool_new:N \l__deriv_pkg_italic_bool 24 | \bool_new:N \l__deriv_pkg_upright_bool 25 | 26 | \keys_define:nn { deriv/pkg } 27 | { 28 | italic .choice:, 29 | italic .usage:n = { load }, 30 | italic .default:n = { true }, 31 | italic / true .code:n = 32 | { 33 | \bool_set_true:N \l__deriv_pkg_italic_bool 34 | \bool_set_false:N \l__deriv_pkg_upright_bool 35 | }, 36 | italic / false .code:n = 37 | { 38 | \bool_set_false:N \l__deriv_pkg_italic_bool 39 | \bool_set_true:N \l__deriv_pkg_upright_bool 40 | }, 41 | italic / unknown .code:n = { \msg_error:nnx { deriv } { boolean-values-only } \l_keys_key_str }, 42 | 43 | upright .choice:, 44 | upright .usage:n = { load }, 45 | upright .default:n = { true }, 46 | upright / true .code:n = 47 | { 48 | \bool_set_true:N \l__deriv_pkg_upright_bool 49 | \bool_set_false:N \l__deriv_pkg_italic_bool 50 | }, 51 | upright / false .code:n = 52 | { 53 | \bool_set_false:N \l__deriv_pkg_upright_bool 54 | \bool_set_true:N \l__deriv_pkg_italic_bool 55 | }, 56 | upright / unknown .code:n = { \msg_error:nnx { deriv } { boolean-values-only } \l_keys_key_str }, 57 | upright .initial:n = true, 58 | } 59 | 60 | \ProcessKeysPackageOptions{ deriv/pkg } 61 | 62 | %%%%% Useful conditionals %%%%% 63 | 64 | \prg_new_conditional:Npnn \__deriv_if_value:n #1 { T, TF } 65 | { 66 | \tl_if_novalue:nTF {#1} 67 | { \prg_return_false: } 68 | { 69 | \tl_if_blank:nTF {#1} 70 | { \prg_return_false: } 71 | { \prg_return_true: } 72 | } 73 | } 74 | 75 | \prg_new_conditional:Npnn \__deriv_show_order:N #1 { T, TF } 76 | { 77 | \str_if_eq:NNTF #1 1 78 | { \prg_return_false: } 79 | { \prg_return_true: } 80 | } 81 | 82 | \prg_new_protected_conditional:Npnn \__deriv_if_in_two_seq:NNNN #1 #2 #3 #4 { TF } 83 | { 84 | \int_zero:N \l__deriv_seq_pos_int 85 | \seq_map_indexed_inline:Nn #1 86 | { 87 | \str_if_eq:VnT #3 {##2} %todo choose correct check 88 | { 89 | \tl_set:Nf \l__deriv_tmpa_tl { \seq_item:Nn #2 {##1} } 90 | \tl_if_eq:NNT #4 \l__deriv_tmpa_tl 91 | { \seq_map_break:n { \int_set:Nn \l__deriv_seq_pos_int {##1} } } 92 | } 93 | } 94 | \int_compare:nNnTF \l__deriv_seq_pos_int = 0 95 | { \prg_return_false: } 96 | { \prg_return_true: } 97 | } 98 | 99 | %%%%% Variables: derivatives %%%%% 100 | 101 | \tl_new:N \l__deriv_dv_denom_tl 102 | 103 | \seq_new:N \l__deriv_dv_var_seq 104 | \seq_new:N \l__deriv_dv_order_seq 105 | 106 | \seq_new:N \l__deriv_dv_variant_seq 107 | 108 | %%%%% Variables: differential %%%%% 109 | 110 | \seq_new:N \l__deriv_i_var_seq 111 | \seq_new:N \l__deriv_i_order_seq 112 | \tl_new:N \l__deriv_i_denom_tl 113 | 114 | \seq_new:N \l__deriv_i_variant_seq 115 | 116 | %%%%% Variables: other %%%%% 117 | 118 | \tl_new:N \l__deriv_cs_name_tl 119 | \tl_new:N \l__deriv_derivset_tl 120 | \bool_new:N \l__deriv_first_unknown_key_bool 121 | 122 | \tl_new:N \l__deriv_gcd_result_tl 123 | \tl_new:N \l__deriv_gcd_remain_tl 124 | \int_new:N \l__deriv_gcd_counter_int 125 | 126 | \tl_new:N \l__deriv_tmpa_tl 127 | \tl_new:N \l__deriv_tmpb_tl 128 | \tl_new:N \l__deriv_tmpc_tl 129 | \seq_new:N \l__deriv_tmpa_seq 130 | 131 | \seq_new:N \l__deriv_new_var_seq 132 | \seq_new:N \l__deriv_rubber_seq 133 | \seq_new:N \l__deriv_add_var_bool_seq 134 | 135 | \int_new:N \l__deriv_vmo_int 136 | 137 | \seq_new:N \l__deriv_num_tmpa_seq 138 | \seq_new:N \l__deriv_num_tmpb_seq 139 | \seq_new:N \l__deriv_sym_tmpa_seq 140 | \seq_new:N \l__deriv_sym_tmpb_seq 141 | 142 | \tl_new:N \l__deriv_sym_tmpa_tl 143 | \tl_new:N \l__deriv_num_tmpa_tl 144 | \tl_new:N \l__deriv_sym_tmpb_tl 145 | \tl_new:N \l__deriv_num_tmpb_tl 146 | \tl_new:N \l__deriv_input_tl 147 | 148 | \seq_new:N \l__deriv_input_seq 149 | \seq_new:N \l__deriv_extract_seq 150 | \seq_new:N \l__deriv_permutation_seq 151 | \seq_new:N \l__deriv_sorted_seq 152 | \seq_new:N \l__deriv_symbol_seq 153 | \seq_new:N \l__deriv_number_seq 154 | 155 | \int_new:N \l__deriv_var_count_int 156 | \int_new:N \l__deriv_tmpa_int 157 | \int_new:N \l__deriv_tmpb_int 158 | 159 | \tl_new:N \l__deriv_numerical_tl 160 | \int_new:N \l__deriv_seq_pos_int 161 | \int_new:N \l__deriv_sort_max_int 162 | 163 | \regex_const:Nn \c__deriv_cs_numbers_regex { \A\-?\d+(?:,\d+){0,2}\Z } 164 | \tl_const:Nn \c__deriv_digits_tl {123456789-0} 165 | 166 | %%%%% default values %%%%% 167 | \prop_const_from_keyval:Nn \c__deriv_dv_pkg_keys_prop 168 | { 169 | style-inf-num = d, 170 | style-inf-den = d, 171 | style-frac = \frac, 172 | style-frac-/ = \slashfrac, 173 | style-var = single, 174 | style-var-/ = single, 175 | style-var-! = multiple, 176 | style-var-/! = single, 177 | scale-eval = auto, 178 | scale-eval-/ = auto, 179 | scale-eval-! = auto, 180 | scale-fun = auto, 181 | scale-var = auto, 182 | scale-var-! = auto, 183 | scale-frac = auto, 184 | scale-frac-/ = auto, 185 | delims-eval = .\rvert, 186 | delims-eval-/ = .\rvert, 187 | delims-eval-! = .\rvert, 188 | delims-fun = (), 189 | delims-var = (), 190 | delims-var-! = (), 191 | delims-frac = (), 192 | delims-frac-/ = (), 193 | sep-inf-ord = 0, 194 | sep-inf-fun = 0, 195 | sep-ord-fun = 0, 196 | sep-frac-fun = 0, 197 | sep-inf-var = 0, 198 | sep-var-ord = 0, 199 | sep-var-inf = \mathop{}\!, 200 | sep-ord-inf = \mathop{}\!, 201 | sep-ord-ord = {,}, 202 | sep-ord-var = 0, 203 | sep-var-var = {,}, 204 | sep-eval-sb = 0, 205 | sep-eval-sp = 0, 206 | switch-* = false, 207 | switch-/ = false, 208 | switch-! = false, 209 | switch-sort = true, 210 | sort-method = {sign, symbol, abs}, 211 | sort-numerical = auto, 212 | sort-abs-reverse = false, 213 | sort-number-reverse = false, 214 | sort-sign-reverse = false, 215 | sort-symbol-reverse = false, 216 | sort-lexical-reverse = false, 217 | fun = false, 218 | frac = false, 219 | var = none, 220 | order = 1, 221 | mixed-order = 1 222 | } 223 | 224 | \prop_const_from_keyval:Nn \c__deriv_i_pkg_keys_prop 225 | { 226 | style-inf = d, 227 | style-var = multiple, 228 | style-var-* = single, 229 | scale-var = auto, 230 | scale-var-* = auto, 231 | delims-var = (), 232 | delims-var-* = (), 233 | sep-begin = \mathop{}\!, 234 | sep-inf-ord = 0, 235 | sep-inf-var = 0, 236 | sep-ord-var = 0, 237 | sep-var-inf = \mathop{}\!, 238 | sep-var-var = {,}, 239 | sep-ord-ord = {,}, 240 | sep-end = 0, 241 | switch-* = false, 242 | var = none, 243 | order = 1 244 | } 245 | 246 | %%%%%% Key-val for all %%%%%% 247 | 248 | \prop_new:N \l__deriv_all_all_user_keys_prop 249 | \prop_const_from_keyval:Nn \c__deriv_all_pkg_keys_prop 250 | { scale-auto = leftright } 251 | 252 | \keys_define:nn { deriv/all/all } 253 | { 254 | scale-auto .choice:, 255 | scale-auto / leftright .code:n = 256 | { 257 | \cs_set_eq:NN \__deriv_auto_left:n \left 258 | \cs_set_eq:NN \__deriv_auto_right:n \right 259 | }, 260 | scale-auto / mleftmright .code:n = 261 | { 262 | \cs_set_eq:NN \__deriv_auto_left:n \mleft 263 | \cs_set_eq:NN \__deriv_auto_right:n \mright 264 | } 265 | } 266 | 267 | %%%%%% Key-val: Derivative %%%%%% 268 | 269 | % variant 270 | \cs_new:Npn \__deriv_dv_define_keys:n #1 271 | { 272 | \keys_define:nn { deriv/dv/#1 } 273 | { 274 | style-inf .meta:n = { style-inf-num={##1}, style-inf-den={##1} }, 275 | style-inf-num .tl_set:c = { l__deriv_dv_#1_style_inf_num_tl }, 276 | style-inf-den .tl_set:c = { l__deriv_dv_#1_style_inf_den_tl }, 277 | style-var .choices:nn = { single, multiple } { \__deriv_dv_set_style_var:nnn {dv_#1} {##1} { } }, 278 | style-var-/ .choices:nn = { single, multiple } { \__deriv_dv_set_style_var:nnn {dv_#1} {##1} { _slash } }, 279 | style-var-! .choices:nn = { single, multiple, mixed } { \__deriv_i_set_style_var:nnn {dv_#1} {##1} { _compact } }, 280 | style-var-/! .choices:nn = { single, multiple, mixed } { \__deriv_i_set_style_var:nnn {dv_#1} {##1} { _slash_compact } }, 281 | style-frac .cs_set:cp = { __deriv_dv_#1_style_frac:nn } {##1}, 282 | style-frac-/ .cs_set:cp = { __deriv_dv_#1_style_frac_slash:nn } {##1}, 283 | 284 | scale-eval .choices:nn = { auto, none, big, Big, bigg, Bigg } { \__deriv_set_scale:nnn {dv_#1} {##1} { eval } }, 285 | scale-eval-/ .choices:nn = { auto, none, big, Big, bigg, Bigg } { \__deriv_set_scale:nnn {dv_#1} {##1} { eval_slash } }, 286 | scale-eval-! .choices:nn = { auto, none, big, Big, bigg, Bigg } { \__deriv_set_scale:nnn {dv_#1} {##1} { eval_compact } }, 287 | scale-fun .choices:nn = { auto, none, big, Big, bigg, Bigg } { \__deriv_set_scale:nnn {dv_#1} {##1} { fun } }, 288 | scale-var .choices:nn = { auto, none, big, Big, bigg, Bigg } { \__deriv_set_scale:nnn {dv_#1} {##1} { var } }, 289 | scale-var-! .choices:nn = { auto, none, big, Big, bigg, Bigg } { \__deriv_set_scale:nnn {dv_#1} {##1} { var_compact } }, 290 | scale-frac .choices:nn = { auto, none, big, Big, bigg, Bigg } { \__deriv_set_scale:nnn {dv_#1} {##1} { frac } }, 291 | scale-frac-/ .choices:nn = { auto, none, big, Big, bigg, Bigg } { \__deriv_set_scale:nnn {dv_#1} {##1} { frac_slash } }, 292 | 293 | delims-eval .tl_set:c = { l__deriv_dv_#1_delims_eval_tl }, 294 | delims-eval-/ .tl_set:c = { l__deriv_dv_#1_delims_eval_slash_tl }, 295 | delims-eval-! .tl_set:c = { l__deriv_dv_#1_delims_eval_compact_tl }, 296 | delims-fun .tl_set:c = { l__deriv_dv_#1_delims_fun_tl }, 297 | delims-var .tl_set:c = { l__deriv_dv_#1_delims_var_tl }, 298 | delims-var-! .tl_set:c = { l__deriv_dv_#1_delims_var_compact_tl }, 299 | delims-frac .tl_set:c = { l__deriv_dv_#1_delims_frac_tl }, 300 | delims-frac-/ .tl_set:c = { l__deriv_dv_#1_delims_frac_slash_tl }, 301 | 302 | sep-inf-ord .code:n = { \__deriv_set_rubber_length:cn { l__deriv_dv_#1_sep_inf_ord_tl } {##1} }, 303 | sep-inf-fun .code:n = { \__deriv_set_rubber_length:cn { l__deriv_dv_#1_sep_inf_fun_tl } {##1} }, 304 | sep-ord-fun .code:n = { \__deriv_set_rubber_length:cn { l__deriv_dv_#1_sep_ord_fun_tl } {##1} }, 305 | sep-frac-fun .code:n = { \__deriv_set_rubber_length:cn { l__deriv_dv_#1_sep_frac_fun_tl } {##1} }, 306 | sep-inf-var .code:n = { \__deriv_set_rubber_length:cn { l__deriv_dv_#1_sep_inf_var_tl } {##1} }, 307 | sep-var-ord .code:n = { \__deriv_set_rubber_length:cn { l__deriv_dv_#1_sep_var_ord_tl } {##1} }, 308 | sep-var-inf .code:n = { \__deriv_set_rubber_length:cn { l__deriv_dv_#1_sep_var_inf_tl } {##1} }, 309 | sep-ord-inf .code:n = { \__deriv_set_rubber_length:cn { l__deriv_dv_#1_sep_ord_inf_tl } {##1} }, 310 | sep-ord-ord .code:n = { \__deriv_set_rubber_length:cn { l__deriv_dv_#1_sep_ord_ord_tl } {##1} }, 311 | sep-ord-var .code:n = { \__deriv_set_rubber_length:cn { l__deriv_dv_#1_sep_ord_var_tl } {##1} }, 312 | sep-var-var .code:n = { \__deriv_set_rubber_length:cn { l__deriv_dv_#1_sep_var_var_tl } {##1} }, 313 | sep-eval-sb .code:n = { \__deriv_set_rubber_length:cn { l__deriv_dv_#1_sep_eval_sb_tl } {##1} }, 314 | sep-eval-sp .code:n = { \__deriv_set_rubber_length:cn { l__deriv_dv_#1_sep_eval_sp_tl } {##1} }, 315 | 316 | switch-* .bool_set:c = { l__deriv_dv_#1_switch_star_bool }, 317 | switch-/ .bool_set:c = { l__deriv_dv_#1_switch_slash_bool }, 318 | switch-! .bool_set:c = { l__deriv_dv_#1_switch_compact_bool }, 319 | switch-sort .bool_set:c = { l__deriv_dv_#1_switch_sort_bool }, 320 | 321 | sort-method .code:n = { \__deriv_set_sort_method:nn {#1} {##1} }, 322 | sort-numerical .choices:nn = { auto, first, last, symbolic } { \tl_set:cn { l__deriv_dv_#1_sort_numerical_tl } {##1} }, 323 | sort-abs-reverse .bool_set:c = { l__deriv_dv_#1_sort_abs_reverse_bool }, 324 | sort-lexical-reverse .bool_set:c = { l__deriv_dv_#1_sort_lexical_reverse_bool }, 325 | sort-number-reverse .bool_set:c = { l__deriv_dv_#1_sort_number_reverse_bool }, 326 | sort-sign-reverse .bool_set:c = { l__deriv_dv_#1_sort_sign_reverse_bool }, 327 | sort-symbol-reverse .bool_set:c = { l__deriv_dv_#1_sort_symbol_reverse_bool }, 328 | 329 | fun .bool_set:c = { l__deriv_dv_#1_misc_fun_bool }, 330 | frac .bool_set:c = { l__deriv_dv_#1_misc_frac_bool }, 331 | var .clist_set:c = { l__deriv_dv_#1_misc_var_clist }, 332 | var .default:n = { all }, 333 | 334 | order .clist_set:c = { l__deriv_dv_#1_misc_order_clist }, 335 | ord .meta:n = { order={##1} }, 336 | mixed-order .tl_set:c = { l__deriv_dv_#1_misc_mixed_order_tl }, 337 | mixord .meta:n = { mixed-order={##1} }, 338 | 339 | unknown .code:n = 340 | { 341 | \bool_if:NT \l__deriv_first_unknown_key_bool 342 | { 343 | \clist_clear:c { l__deriv_dv_#1_misc_order_clist } 344 | \bool_set_false:N \l__deriv_first_unknown_key_bool 345 | } 346 | \exp_args:NnnV \tl_set_rescan:Nnn \l__deriv_tmpa_tl { } \l_keys_key_str 347 | \clist_put_right:cV { l__deriv_dv_#1_misc_order_clist } \l__deriv_tmpa_tl 348 | } 349 | } 350 | } 351 | 352 | %%%%%% Key-val: Differential %%%%%% 353 | 354 | % variant 355 | \cs_new:Npn \__deriv_i_define_keys:n #1 356 | { 357 | \keys_define:nn { deriv/i/#1 } 358 | { 359 | style-inf .tl_set:c = { l__deriv_i_#1_style_inf_tl }, 360 | style-var .choices:nn = { single, multiple, mixed } { \__deriv_i_set_style_var:nnn {i_#1} {##1} { } }, 361 | style-var-* .choices:nn = { single, multiple, mixed } { \__deriv_i_set_style_var:nnn {i_#1} {##1} { _star } }, 362 | 363 | scale-var .choices:nn = { auto, none, big, Big, bigg, Bigg } { \__deriv_set_scale:nnn {i_#1} {##1} { var } }, 364 | scale-var-* .choices:nn = { auto, none, big, Big, bigg, Bigg } { \__deriv_set_scale:nnn {i_#1} {##1} { var_star } }, 365 | 366 | delims-var .tl_set:c = { l__deriv_i_#1_delims_var_tl }, 367 | delims-var-* .tl_set:c = { l__deriv_i_#1_delims_var_star_tl }, 368 | 369 | sep-begin .code:n = { \__deriv_set_rubber_length:cn { l__deriv_i_#1_sep_begin_tl } {##1} }, 370 | sep-inf-ord .code:n = { \__deriv_set_rubber_length:cn { l__deriv_i_#1_sep_inf_ord_tl } {##1} }, 371 | sep-inf-var .code:n = { \__deriv_set_rubber_length:cn { l__deriv_i_#1_sep_inf_var_tl } {##1} }, 372 | sep-ord-var .code:n = { \__deriv_set_rubber_length:cn { l__deriv_i_#1_sep_ord_var_tl } {##1} }, 373 | sep-var-inf .code:n = { \__deriv_set_rubber_length:cn { l__deriv_i_#1_sep_var_inf_tl } {##1} }, 374 | sep-var-var .code:n = { \__deriv_set_rubber_length:cn { l__deriv_i_#1_sep_var_var_tl } {##1} }, 375 | sep-ord-ord .code:n = { \__deriv_set_rubber_length:cn { l__deriv_i_#1_sep_ord_ord_tl } {##1} }, 376 | sep-end .code:n = { \__deriv_set_rubber_length:cn { l__deriv_i_#1_sep_end_tl } {##1} }, 377 | 378 | switch-* .bool_set:c = { l__deriv_i_#1_switch_star_bool }, 379 | 380 | var .clist_set:c = { l__deriv_i_#1_misc_var_clist }, 381 | var .default:n = {all}, 382 | 383 | order .clist_set:c = { l__deriv_i_#1_misc_order_clist }, 384 | ord .meta:n = { order={##1} }, 385 | 386 | unknown .code:n = 387 | { 388 | \bool_if:NT \l__deriv_first_unknown_key_bool 389 | { 390 | \clist_clear:c { l__deriv_i_#1_misc_order_clist } 391 | \bool_set_false:N \l__deriv_first_unknown_key_bool 392 | } 393 | \exp_args:NnnV \tl_set_rescan:Nnn \l__deriv_tmpa_tl { } \l_keys_key_str 394 | \clist_put_right:cV { l__deriv_i_#1_misc_order_clist } \l__deriv_tmpa_tl 395 | } 396 | } 397 | } 398 | 399 | % variant, value 400 | \cs_new:Npn \__deriv_set_sort_method:nn #1 #2 401 | { 402 | \seq_clear:c { l__deriv_dv_#1_sort_method_seq } 403 | \seq_set_from_clist:Nn \l__deriv_tmpa_seq {#2} 404 | 405 | \seq_map_indexed_inline:Nn \l__deriv_tmpa_seq 406 | { 407 | \str_case:nn {##2} 408 | { 409 | { sign } { \seq_put_right:cn { l__deriv_dv_#1_sort_method_seq } { \__deriv_sort_sign:n } } 410 | { symbol } { \seq_put_right:cn { l__deriv_dv_#1_sort_method_seq } { \__deriv_sort_symbol:n } } 411 | { abs } { \seq_put_right:cn { l__deriv_dv_#1_sort_method_seq } { \__deriv_sort_abs:n } } 412 | { number } { \seq_put_right:cn { l__deriv_dv_#1_sort_method_seq } { \__deriv_sort_number:n } } 413 | { lexical } { \seq_put_right:cn { l__deriv_dv_#1_sort_method_seq } { \__deriv_sort_lexical:n } } 414 | } 415 | \int_compare:nNnT {##1} = { 3 } { \seq_map_break: } 416 | } 417 | } 418 | % variant, value, name 419 | \cs_new:Npn \__deriv_dv_set_style_var:nnn #1 #2 #3 420 | { \exp_args:Nnc \tl_set:cn { l__deriv_#1_style_var#3_tl } { __deriv_dv_build_var_#2:NNNnn } } 421 | 422 | \cs_new:Npn \__deriv_i_set_style_var:nnn #1 #2 #3 423 | { \exp_args:Nnc \tl_set:cn { l__deriv_#1_style_var#3_tl } { __deriv_i_build_var_#2:NNNnnn } } 424 | 425 | % dv_variant, scale, name 426 | \cs_new:Npn \__deriv_set_scale:nnn #1 #2 #3 427 | { 428 | \str_case:nnF {#2} 429 | { 430 | { auto } { \tl_set:cn { l__deriv_#1_scale_#3_tl } { \__deriv_scale_auto:nnn } } 431 | { none } { \tl_set:cn { l__deriv_#1_scale_#3_tl } { \__deriv_scale_none:nnn } } 432 | } 433 | { \tl_set:cn { l__deriv_#1_scale_#3_tl } { \__deriv_scale_big:nnnn {#2} } } 434 | } 435 | % muskip, tl 436 | \cs_new:Npn \__deriv_set_rubber_length:Nn #1 #2 437 | { 438 | \regex_match:NnTF \c__deriv_cs_numbers_regex {#2} 439 | { 440 | \str_case:nnF {#2} 441 | { 442 | { 0 } { \tl_clear:N #1 } 443 | { 0,0 } { \tl_clear:N #1 } 444 | { 0,0,0 } { \tl_clear:N #1 } 445 | } 446 | { 447 | \seq_set_split:Nnn \l__deriv_rubber_seq { , } {#2} 448 | \tl_set:Nf #1 { \seq_use:Nnnn \l__deriv_rubber_seq { mu plus } { mu plus } { mu minus } mu } 449 | \tl_put_left:Nn #1 { \mskip } 450 | } 451 | } 452 | { \tl_set:Nn #1 {#2} } 453 | } 454 | 455 | %%%%% Setting keys %%%%% 456 | 457 | \DeclareDocumentCommand{\derivset}{ m o } 458 | { 459 | \str_if_eq:nnTF {#1} { all } 460 | { 461 | \__deriv_set_default:nnn { all } {#2} { all } 462 | \keys_set:nn { deriv/all/all } { default } 463 | } 464 | { 465 | \tl_set:Nx \l__deriv_derivset_tl { \cs_to_str:N #1 } 466 | \deriv_set_keys:Vn \l__deriv_derivset_tl {#2} 467 | } 468 | } 469 | % dv, keyval 470 | \cs_new_protected:Npn \deriv_set_keys:nn #1 #2 471 | { 472 | \seq_if_in:NnTF \l__deriv_dv_variant_seq {#1} 473 | { \__deriv_set_default:nnn {#1} {#2} { dv } } 474 | { 475 | \seq_if_in:NnTF \l__deriv_i_variant_seq {#1} 476 | { \__deriv_set_default:nnn {#1} {#2} { i } } 477 | { 478 | \msg_error:nnxx { deriv } { derivative-not-defined } 479 | { \token_to_str:N #1 } 480 | { \token_to_str:N \derivset } 481 | } 482 | } 483 | } 484 | % keyval, dv/i, variant 485 | \cs_new_protected:Npn \deriv_local_keys:nnn #1 #2 #3 486 | { 487 | \bool_set_true:N \l__deriv_first_unknown_key_bool 488 | \tl_if_novalue:nTF {#1} 489 | { 490 | \bool_if:cT { l__deriv_#2_#3_local_keys_bool } 491 | { 492 | \keys_set:nn { deriv/#2/#3 } { default } 493 | \bool_set_false:c { l__deriv_#2_#3_local_keys_bool } 494 | } 495 | } 496 | { 497 | \bool_if:cTF { l__deriv_#2_#3_local_keys_bool } 498 | { \keys_set:nn { deriv/#2/#3 } { default, #1 } } 499 | { \keys_set:nn { deriv/#2/#3 } {#1} } 500 | \bool_set_true:c { l__deriv_#2_#3_local_keys_bool } 501 | } 502 | } 503 | %%%%% Declaring variants %%%%% 504 | 505 | % tl-dv, macro, inf, keyval, dv/i 506 | \cs_new_protected:Npn \deriv_preamble:NNnnn #1 #2 #3 #4 #5 507 | { 508 | \tl_set:Nx #1 { \cs_to_str:N #2 } 509 | 510 | \tl_if_novalue:nTF {#4} 511 | { \__deriv_preamble_aux:Vnn #1 { style-inf={#3} } {#5} } 512 | { \__deriv_preamble_aux:Vnn #1 { style-inf={#3}, #4} {#5} } 513 | } 514 | % variant, key-value, dv/i 515 | \cs_new_protected:Npn \__deriv_preamble_aux:nnn #1 #2 #3 516 | { 517 | \seq_if_in:cnF { l__deriv_#3_variant_seq } {#1} 518 | { 519 | \seq_put_left:cn { l__deriv_#3_variant_seq } {#1} 520 | \use:c { __deriv_#3_variables:n } {#1} 521 | \use:c { __deriv_#3_define_keys:n } {#1} 522 | } 523 | \prop_set_eq:cc { l__deriv_#3_#1_user_keys_prop } { c__deriv_#3_pkg_keys_prop } 524 | \__deriv_set_default:nnn {#1} {#2} {#3} 525 | } 526 | % data-type, variant, category, cs-var-list 527 | \cs_new:Npn \__deriv_new:nnnnn #1 #2 #3 #4 #5 528 | { 529 | \seq_set_from_clist:Nn \l__deriv_new_var_seq {#5} 530 | \seq_map_inline:Nn \l__deriv_new_var_seq 531 | { \use:c { #1_new:c } { l__deriv_#2_#3_#4_##1_#1 } } 532 | } 533 | % variant 534 | \cs_new_protected:Npn \__deriv_dv_variables:n #1 535 | { 536 | \__deriv_new:nnnnn { tl } { dv } {#1} { style } { inf_num, inf_den, var, var_compact, var_slash_compact, frac, frac_slash } 537 | \__deriv_new:nnnnn { tl } { dv } {#1} { scale } { eval, eval_slash, eval_compact, fun, var, var_compact, frac, frac_slash } 538 | \__deriv_new:nnnnn { tl } { dv } {#1} { delims } { eval, eval_slash, eval_comapct, fun, var, frac, frac_slash } 539 | \__deriv_new:nnnnn { tl } { dv } {#1} { sep } { inf_ord, inf_fun, ord_fun, frac_fun, inf_var, var_ord, var_inf, ord_inf, ord_ord, ord_var, var_var, eval_sb, eval_sp } 540 | \__deriv_new:nnnnn { bool } { dv } {#1} { switch } { star, slash, compact, sort } 541 | \__deriv_new:nnnnn { seq } { dv } {#1} { sort } { method } 542 | \__deriv_new:nnnnn { tl } { dv } {#1} { sort } { numerical } 543 | \__deriv_new:nnnnn { bool } { dv } {#1} { sort } { abs_reverse, sign_reverse, symbol_reverse, number_reverse, lexical_reverse } 544 | \__deriv_new:nnnnn { bool } { dv } {#1} { misc } { fun, frac } 545 | \__deriv_new:nnnnn { clist } { dv } {#1} { misc } { var } 546 | \__deriv_new:nnnnn { clist } { dv } {#1} { misc } { order } 547 | \__deriv_new:nnnnn { tl } { dv } {#1} { misc } { mixed_order } 548 | \__deriv_new:nnnnn { prop } { dv } {#1} { user } { keys } 549 | \__deriv_new:nnnnn { bool } { dv } {#1} { local } { keys } 550 | } 551 | % variant 552 | \cs_new_protected:Npn \__deriv_i_variables:n #1 553 | { 554 | \__deriv_new:nnnnn { tl } { i } {#1} { style } { inf, var, var_star } 555 | \__deriv_new:nnnnn { tl } { i } {#1} { scale } { var, var_star } 556 | \__deriv_new:nnnnn { tl } { i } {#1} { delims } { var, var_star } 557 | \__deriv_new:nnnnn { tl } { i } {#1} { sep } { begin, inf_ord, inf_var, ord_var, var_inf, var_var, ord_ord, end } 558 | \__deriv_new:nnnnn { bool } { i } {#1} { switch } { star } 559 | \__deriv_new:nnnnn { bool } { i } {#1} { mics } { fun, var, frac } 560 | \__deriv_new:nnnnn { clist } { i } {#1} { misc } { order } 561 | \__deriv_new:nnnnn { prop } { i } {#1} { user } { keys } 562 | \__deriv_new:nnnnn { bool } { i } {#1} { local } { keys } 563 | } 564 | % variant, keyval, dv/i 565 | \cs_new_protected:Npn \__deriv_set_default:nnn #1 #2 #3 566 | { 567 | \tl_if_novalue:nTF {#2} 568 | { \prop_set_eq:cc { l__deriv_#3_#1_user_keys_prop } { c__deriv_#3_pkg_keys_prop } } 569 | { \prop_put_from_keyval:cn { l__deriv_#3_#1_user_keys_prop } {#2} } 570 | 571 | \__deriv_set_default_auxi:cnn { l__deriv_#3_#1_user_keys_prop } {#1} {#3} 572 | \keys_set:nn { deriv/#3/#1 } { default } 573 | } 574 | % prop-key-val, variant, dv/i 575 | \cs_new_protected:Npn \__deriv_set_default_auxi:Nnn #1 #2 #3 576 | { \__deriv_set_default_auxii:fnn { \prop_to_keyval:N #1 } {#2} {#3} } 577 | % key-val, variant, dv/i 578 | \cs_new_protected:Npn \__deriv_set_default_auxii:nnn #1 #2 #3 579 | { \keys_define:nn { deriv/#3/#2 } { default .meta:n = {#1} } } 580 | % new/delare/renew/provide, variant, macro 581 | \cs_new_protected:Npn \deriv_dv_define:Nnn #1 #2 #3 582 | { 583 | \exp_args:Nne #1 {#3}{ s o m t/ t! m !e{\char_generate:nn {`_}{8}^} } 584 | { 585 | \group_begin: 586 | \deriv_local_keys:nnn {##2} { dv } {#2} 587 | 588 | \exp_args:Nnc \bool_xor:nnTF {##5} { l__deriv_dv_#2_switch_compact_bool } 589 | { 590 | \exp_args:Nnc \bool_xor:nnTF {##4} { l__deriv_dv_#2_switch_slash_bool } 591 | { \__deriv_dv_slash_compact:nnnnn {dv_#2} {##3} {##6} {##7} {##8} } 592 | { \__deriv_dv_compact:nnnnn {dv_#2} {##3} {##6} {##7} {##8} } 593 | } 594 | { 595 | \exp_args:Nnc \bool_xor:nnTF {##4} { l__deriv_dv_#2_switch_slash_bool } 596 | { 597 | \exp_args:Nnc \bool_xor:nnTF {##1} { l__deriv_dv_#2_switch_star_bool } 598 | { \__deriv_dv_star_slash:nnnnn {dv_#2} {##3} {##6} {##7} {##8} } 599 | { \__deriv_dv_slash:nnnnn {dv_#2} {##3} {##6} {##7} {##8} } 600 | } 601 | { 602 | \exp_args:Nnc \bool_xor:nnTF {##1} { l__deriv_dv_#2_switch_star_bool } 603 | { \__deriv_dv_star:nnnnn {dv_#2} {##3} {##6} {##7} {##8} } 604 | { \__deriv_dv_none:nnnnn {dv_#2} {##3} {##6} {##7} {##8} } 605 | } 606 | } 607 | \group_end: 608 | } 609 | } 610 | % new/delare/renew/provide, variant, macro 611 | \cs_new_protected:Npn \deriv_i_define:Nnn #1 #2 #3 612 | { 613 | #1 {#3}{ s o m } 614 | { 615 | \group_begin: 616 | \deriv_local_keys:nnn {##2} { i } {#2} 617 | 618 | \exp_args:Nnc \bool_xor:nnTF {##1} { l__deriv_i_#2_switch_star_bool } 619 | { \__deriv_inf_star:nn {i_#2} {##3} } 620 | { \__deriv_inf_none:nn {i_#2} {##3} } 621 | \group_end: 622 | } 623 | } 624 | 625 | %%%%% derivative definition %%%%% 626 | % variant, function, variable, sb-point, sp-point 627 | \cs_new_protected:Npn \__deriv_dv_star_slash:nnnnn #1 #2 #3 #4 #5 628 | { 629 | \__deriv_dv_preparation:Nnnn \l__deriv_dv_denom_tl {#1} {#3} { _slash } 630 | \__deriv_evaluation_slash:nnnn {#1} {#4} {#5} 631 | { 632 | \__deriv_fraction_slash:nn {#1} 633 | { 634 | \use:c { __deriv_#1_style_frac_slash:nn } 635 | { \__deriv_dv_numerator_nofun:n {#1} } 636 | { \__deriv_dv_denominator:n {#1} } 637 | } 638 | \__deriv_insert_fun:nnn {#1} {#2} { frac_fun } 639 | } 640 | } 641 | % variant, function, variable, sb-point, sp-point 642 | \cs_new_protected:Npn \__deriv_dv_star:nnnnn #1 #2 #3 #4 #5 643 | { 644 | \__deriv_dv_preparation:Nnnn \l__deriv_dv_denom_tl {#1} {#3} { } 645 | \__deriv_evaluation:nnnn {#1} {#4} {#5} 646 | { 647 | \__deriv_fraction:nn {#1} 648 | { 649 | \use:c { __deriv_#1_style_frac:nn } 650 | { \__deriv_dv_numerator_nofun:n {#1} } 651 | { \__deriv_dv_denominator:n {#1} } 652 | } 653 | \__deriv_insert_fun:nnn {#1} {#2} { frac_fun } 654 | } 655 | } 656 | % variant, function, variable, sb-point, sp-point 657 | \cs_new_protected:Npn \__deriv_dv_slash:nnnnn #1 #2 #3 #4 #5 658 | { 659 | \__deriv_dv_preparation:Nnnn \l__deriv_dv_denom_tl {#1} {#3} { _slash } 660 | \__deriv_evaluation_slash:nnnn {#1} {#4} {#5} 661 | { 662 | \__deriv_fraction_slash:nn {#1} 663 | { 664 | \use:c { __deriv_#1_style_frac_slash:nn } 665 | { \__deriv_dv_numerator_fun:nn {#1} {#2} } 666 | { \__deriv_dv_denominator:n {#1} } 667 | } 668 | } 669 | } 670 | % variant, function, variable, sb-point, sp-point 671 | \cs_new_protected:Npn \__deriv_dv_none:nnnnn #1 #2 #3 #4 #5 672 | { 673 | \__deriv_dv_preparation:Nnnn \l__deriv_dv_denom_tl {#1} {#3} { } 674 | \__deriv_evaluation:nnnn {#1} {#4} {#5} 675 | { 676 | \__deriv_fraction:nn {#1} 677 | { 678 | \use:c { __deriv_#1_style_frac:nn } 679 | { \__deriv_dv_numerator_fun:nn {#1} {#2} } 680 | { \__deriv_dv_denominator:n {#1} } 681 | } 682 | } 683 | } 684 | % variant, function, variable, sb-point, sp-point 685 | \cs_new_protected:Npn \__deriv_dv_compact:nnnnn #1 #2 #3 #4 #5 686 | { 687 | \__deriv_i_preparation:Nnnnn \l__deriv_dv_denom_tl {#1} {#3} { _compact } { _num } 688 | \__deriv_evaluation_compact:nnnn {#1} {#4} {#5} 689 | { 690 | \tl_use:N \l__deriv_dv_denom_tl 691 | \__deriv_insert_fun:nnn {#1} {#2} { inf_fun } 692 | } 693 | } 694 | % variant, function, variable, sb-point, sp-point 695 | \cs_new_protected:Npn \__deriv_dv_slash_compact:nnnnn #1 #2 #3 #4 #5 696 | { 697 | \__deriv_i_preparation:Nnnnn \l__deriv_dv_denom_tl {#1} {#3} { _slash_compact } { _num } 698 | \__deriv_evaluation_compact:nnnn {#1} {#4} {#5} 699 | { 700 | %\__deriv_i_print:Nn \l__deriv_i_denom_tl {#1} 701 | \tl_use:N \l__deriv_dv_denom_tl 702 | \__deriv_insert_fun:nnn {#1} {#2} { inf_fun } 703 | } 704 | } 705 | % variant, function 706 | \cs_new_protected:Npn \__deriv_dv_numerator_fun:nn #1 #2 707 | { 708 | \__deriv_insert_numinf:n {#1} 709 | \__deriv_show_order:cTF { l__deriv_#1_misc_mixed_order_tl } 710 | { 711 | \__deriv_insert_ord:cnn { l__deriv_#1_misc_mixed_order_tl } {#1} { inf_ord } 712 | \__deriv_insert_fun:nnn {#1} {#2} { ord_fun } 713 | } 714 | { \__deriv_insert_fun:nnn {#1} {#2} { inf_fun } } 715 | } 716 | % variant 717 | \cs_new_protected:Npn \__deriv_dv_numerator_nofun:n #1 718 | { 719 | \__deriv_insert_numinf:n {#1} 720 | \__deriv_show_order:cT { l__deriv_#1_misc_mixed_order_tl } 721 | { \__deriv_insert_ord:cnn { l__deriv_#1_misc_mixed_order_tl } {#1} { inf_ord } } 722 | } 723 | % dv 724 | \cs_new_protected:Npn \__deriv_dv_denominator:n #1 725 | { \tl_use:N \l__deriv_dv_denom_tl } 726 | 727 | % denom-tl, variant, variable, if star 728 | \cs_new_protected:Npn \__deriv_dv_preparation:Nnnn #1 #2 #3 #4 729 | { 730 | \tl_clear:N #1 731 | \seq_set_from_clist:Nn \l__deriv_dv_var_seq {#3} 732 | \seq_set_from_clist:Nc \l__deriv_dv_order_seq { l__deriv_#2_misc_order_clist } 733 | 734 | \tl_use:c { l__deriv_#2_style_var#4_tl } \l__deriv_dv_var_seq \l__deriv_dv_order_seq #1 {#2} {#4} 735 | 736 | % Legacy development code from when `style-var-/` was not available 737 | %\tl_if_eq:nnTF {#4} { _slash } %TODO: Find a better solution 738 | %{ \tl_use:c { l__deriv_#2_style_var_tl } \l__deriv_dv_var_seq \l__deriv_dv_order_seq #1 {#2} {#4} } 739 | %{ \tl_use:c { l__deriv_#2_style_var#4_tl } \l__deriv_dv_var_seq \l__deriv_dv_order_seq #1 {#2} {#4} } 740 | } 741 | % var_seq, order_seq, denom-tl, variant, if star 742 | \cs_new_protected:Npn \__deriv_dv_build_var_multiple:NNNnn #1 #2 #3 #4 #5 743 | { 744 | \int_set:Nn \l__deriv_var_count_int { \seq_count:N #1 } 745 | \__deriv_adjust_ord_seq:NN \l__deriv_var_count_int #2 746 | 747 | \str_if_eq:cNT { l__deriv_#4_misc_mixed_order_tl } 1 748 | { \__deriv_mixed_order:cNn { l__deriv_#4_misc_mixed_order_tl } #2 {#4} } 749 | 750 | \__deriv_var_bool_seq:cNN { l__deriv_#4_misc_var_clist } \l__deriv_tmpa_seq \l__deriv_var_count_int 751 | 752 | \seq_map_indexed_inline:Nn #1 753 | { 754 | \seq_pop_left:NN #2 \l__deriv_tmpa_tl 755 | \seq_pop_left:NN \l__deriv_tmpa_seq \l__deriv_tmpb_tl 756 | \tl_put_right:Nx #3 757 | { 758 | \__deriv_insert_deninf:n {#4} 759 | \__deriv_insert_mskip:nn {#4} { inf_var } 760 | \__deriv_insert_var:Nnn \l__deriv_tmpb_tl {##2} {#4} 761 | \__deriv_show_order:NTF \l__deriv_tmpa_tl 762 | { 763 | \__deriv_insert_ord:Nnn \l__deriv_tmpa_tl {#4} { var_ord } 764 | \int_compare:nNnF {##1} = { \l__deriv_var_count_int } 765 | { \__deriv_insert_mskip:nn {#4} { ord_inf } } 766 | } 767 | { 768 | \int_compare:nNnF {##1} = { \l__deriv_var_count_int } 769 | { \__deriv_insert_mskip:nn {#4} { var_inf } } 770 | } 771 | } 772 | } 773 | } 774 | % var_seq, order_seq, denom-tl, variant, if star 775 | \cs_new_protected:Npn \__deriv_dv_build_var_single:NNNnn #1 #2 #3 #4 #5 776 | { 777 | \int_set:Nn \l__deriv_var_count_int { \seq_count:N #1 } 778 | \tl_set:Nf \l__deriv_tmpa_tl { \seq_use:Nn #1 { \__deriv_insert_mskip:nn {#4} { var_var } } } 779 | 780 | \__deriv_var_bool_seq:cNN { l__deriv_#4_misc_var_clist } \l__deriv_tmpa_seq \l__deriv_var_count_int 781 | \int_set:Nn \l__deriv_tmpa_int { \seq_count:N #2 } 782 | 783 | % Temporary store the order argument 784 | \tl_set:Nf \l__deriv_tmpb_tl { \seq_use:Nn #2 { \__deriv_insert_mskip:nn {#4} { ord_ord } } } 785 | 786 | \seq_pop_left:NN \l__deriv_tmpa_seq \l__deriv_tmpc_tl 787 | \tl_put_right:Nx #3 788 | { 789 | \__deriv_insert_deninf:n {#4} 790 | \__deriv_insert_mskip:nn {#4} { inf_var } 791 | \__deriv_insert_var:NVn \l__deriv_tmpc_tl \l__deriv_tmpa_tl {#4} 792 | \__deriv_show_order:NT \l__deriv_tmpb_tl 793 | { \__deriv_insert_ord:Nnn \l__deriv_tmpb_tl {#4} { var_ord } } 794 | } 795 | \str_if_eq:cNT { l__deriv_#4_misc_mixed_order_tl } 1 796 | { \tl_set_eq:cN { l__deriv_#4_misc_mixed_order_tl } \l__deriv_tmpb_tl } 797 | } 798 | % var_seq, order_seq 799 | \cs_new_protected:Npn \__deriv_adjust_ord_seq:NN #1 #2 800 | { 801 | \int_set:Nn \l__deriv_vmo_int { #1 - \seq_count:N #2 } 802 | \int_compare:nNnF { \l__deriv_vmo_int } = { 0 } 803 | { 804 | \int_compare:nNnTF { \l__deriv_vmo_int } < { 0 } 805 | { \int_step_inline:nn { -1*\l__deriv_vmo_int } { \seq_pop_right:NN #2 \l__deriv_tmpa_tl } } 806 | { \int_step_inline:nn { \l__deriv_vmo_int } { \seq_put_right:Nn #2 { 1 } } } 807 | } 808 | } 809 | % avd-clist, bool-seq, count 810 | \cs_new_protected:Npn \__deriv_var_bool_seq:NNN #1 #2 #3 811 | { 812 | \seq_clear:N #2 813 | \clist_if_in:NnTF #1 { all } 814 | { \exp_args:NNf \seq_set_from_clist:Nn #2 { \prg_replicate:nn {#3} { \c_true_bool , } } } 815 | { 816 | \clist_if_in:NnTF #1 { none } 817 | { \exp_args:NNf \seq_set_from_clist:Nn #2 { \prg_replicate:nn {#3} { \c_false_bool , } } } 818 | { 819 | \int_step_inline:nn {#3} 820 | { 821 | \clist_if_in:NnTF #1 {##1} 822 | { \seq_put_right:Nn #2 { \c_true_bool } } 823 | { \seq_put_right:Nn #2 { \c_false_bool } } 824 | } 825 | } 826 | } 827 | } 828 | % ord-seq, var-seq 829 | \cs_new_protected:Npn \__deriv_adjust_trailing_ord:NN #1 #2 830 | { 831 | \int_set:Nn \l__deriv_vmo_int { \seq_count:N #2 - \seq_count:N #1 } 832 | 833 | \int_compare:nNnT { \l__deriv_vmo_int } < { 0 } 834 | { 835 | \int_step_inline:nn { -1*\l__deriv_vmo_int } 836 | { \seq_pop_right:NN #1 \l__deriv_tmpa_tl } 837 | } 838 | 839 | \int_step_inline:nn { \seq_count:N #1 } 840 | { 841 | \seq_pop_right:NN #1 \l__deriv_tmpa_tl 842 | \str_if_eq:VnF \l__deriv_tmpa_tl { 1 } 843 | { 844 | \seq_put_right:NV #1 \l__deriv_tmpa_tl 845 | \prg_break: 846 | } 847 | } 848 | } 849 | 850 | %%%%% infinisimal definition %%%%% 851 | % variant, variable 852 | \cs_new:Npn \__deriv_inf_none:nn #1 #2 853 | { 854 | \__deriv_i_preparation:Nnnnn \l__deriv_i_denom_tl {#1} {#2} { } { } 855 | \__deriv_i_print:Nn \l__deriv_i_denom_tl {#1} 856 | } 857 | 858 | % variant, variable 859 | \cs_new:Npn \__deriv_inf_star:nn #1 #2 860 | { 861 | \__deriv_i_preparation:Nnnnn \l__deriv_i_denom_tl {#1} {#2} { _star } { } 862 | \__deriv_i_print:Nn \l__deriv_i_denom_tl {#1} 863 | } 864 | % print-tl, variant 865 | \cs_new:Npn \__deriv_i_print:Nn #1 #2 866 | { 867 | \__deriv_insert_mskip:nn {#2} { begin } 868 | \tl_use:N #1 869 | \__deriv_insert_mskip:nn {#2} { end } 870 | } 871 | % print-tl, variant, variable, if star, inf_variant 872 | \cs_new_protected:Npn \__deriv_i_preparation:Nnnnn #1 #2 #3 #4 #5 873 | { 874 | \tl_clear:N #1 875 | \seq_set_from_clist:Nn \l__deriv_i_var_seq {#3} 876 | \seq_set_from_clist:Nc \l__deriv_i_order_seq { l__deriv_#2_misc_order_clist } 877 | 878 | \tl_if_eq:nnTF {#4} { _slash_compact } %TODO: Find a better solution 879 | { \tl_use:c { l__deriv_#2_style_var#4_tl } \l__deriv_i_var_seq \l__deriv_i_order_seq #1 {#2} { _compact } {#5} } 880 | { \tl_use:c { l__deriv_#2_style_var#4_tl } \l__deriv_i_var_seq \l__deriv_i_order_seq #1 {#2} {#4} {#5} } 881 | %\tl_use:c { l__deriv_#2_style_var#4_tl } \l__deriv_i_var_seq \l__deriv_i_order_seq #1 {#2} {#4} {#5} 882 | } 883 | % var-seq, order-seq, print-tl, variant, if star, inf_variant 884 | \cs_new_protected:Npn \__deriv_i_build_var_single:NNNnnn #1 #2 #3 #4 #5 #6 885 | { 886 | \int_set:Nn \l__deriv_var_count_int { \seq_count:N #1 } 887 | \__deriv_var_bool_seq:cNN { l__deriv_#4_misc_var_clist } \l__deriv_add_var_bool_seq \l__deriv_var_count_int 888 | \__deriv_adjust_trailing_ord:NN #2 #1 889 | 890 | \int_set:Nn \l__deriv_tmpa_int { \seq_count:N #2 } 891 | 892 | \seq_map_indexed_inline:Nn #1 893 | { 894 | \seq_pop_left:NN \l__deriv_add_var_bool_seq \l__deriv_tmpa_tl 895 | \tl_put_right:Nx \l__deriv_tmpb_tl 896 | { 897 | \__deriv_insert_var:Nnnn \l__deriv_tmpa_tl {##2} {#4} {#5} 898 | \int_compare:nNnF {##1} = { \l__deriv_var_count_int } 899 | { \__deriv_insert_mskip:nn {#4} { var_var } } 900 | } 901 | } 902 | \seq_map_indexed_inline:Nn #2 903 | { 904 | \tl_put_right:Nx \l__deriv_tmpc_tl 905 | { 906 | \exp_not:n {##2} 907 | \int_compare:nNnF {##1} = { \l__deriv_tmpa_int } 908 | { \__deriv_insert_mskip:nn {#4} { ord_ord } } 909 | } 910 | } 911 | \tl_put_right:Nx #3 912 | { 913 | \__deriv_insert_inf:nn {#4} {#6} 914 | \sb 915 | { 916 | \__deriv_insert_mskip:nn {#4} { inf_var } 917 | \exp_not:V \l__deriv_tmpb_tl 918 | } 919 | \tl_if_blank:VF \l__deriv_tmpc_tl 920 | { 921 | \sp 922 | { 923 | \__deriv_insert_mskip:nn {#4} { inf_ord } 924 | \exp_not:V \l__deriv_tmpc_tl 925 | } 926 | } 927 | } 928 | } 929 | % var-seq, order-seq, print-tl, variant, if star, inf_variant 930 | \cs_new_protected:Npn \__deriv_i_build_var_multiple:NNNnnn #1 #2 #3 #4 #5 #6 931 | { 932 | \int_set:Nn \l__deriv_var_count_int { \seq_count:N #1 } 933 | \__deriv_var_bool_seq:cNN { l__deriv_#4_misc_var_clist } \l__deriv_add_var_bool_seq \l__deriv_var_count_int 934 | \__deriv_adjust_ord_seq:NN \l__deriv_var_count_int #2 935 | 936 | \seq_map_indexed_inline:Nn #1 937 | { 938 | \seq_pop_left:NN #2 \l__deriv_tmpa_tl 939 | \seq_pop_left:NN \l__deriv_add_var_bool_seq \l__deriv_tmpb_tl 940 | \tl_put_right:Nx #3 941 | { 942 | \__deriv_insert_inf:nn {#4} {#6} 943 | \__deriv_show_order:NTF \l__deriv_tmpa_tl 944 | { 945 | \__deriv_insert_ord:Nnn \l__deriv_tmpa_tl {#4} { inf_ord } 946 | \__deriv_insert_mskip:nn {#4} { ord_var } 947 | } 948 | { \__deriv_insert_mskip:nn {#4} { inf_var } } 949 | 950 | \__deriv_insert_var:Nnnn \l__deriv_tmpb_tl {##2} {#4} {#5} 951 | \int_compare:nNnF {##1} = { \l__deriv_var_count_int } 952 | { \__deriv_insert_mskip:nn {#4} { var_inf } } 953 | } 954 | } 955 | } 956 | % var-seq, order-seq, print-tl, variant, if star, inf_variant 957 | \cs_new_protected:Npn \__deriv_i_build_var_mixed:NNNnnn #1 #2 #3 #4 #5 #6 958 | { 959 | \int_set:Nn \l__deriv_var_count_int { \seq_count:N #1 } 960 | \__deriv_var_bool_seq:cNN { l__deriv_#4_misc_var_clist } \l__deriv_add_var_bool_seq \l__deriv_var_count_int 961 | \__deriv_adjust_ord_seq:NN \l__deriv_var_count_int #2 962 | 963 | \seq_map_indexed_inline:Nn #1 964 | { 965 | \seq_pop_left:NN #2 \l__deriv_tmpa_tl 966 | \seq_pop_left:NN \l__deriv_add_var_bool_seq \l__deriv_tmpb_tl 967 | \tl_put_right:Nx #3 968 | { 969 | \__deriv_insert_inf:nn {#4} {#6} 970 | \__deriv_show_order:NT \l__deriv_tmpa_tl 971 | { \__deriv_insert_ord:Nnn \l__deriv_tmpa_tl {#4} { inf_ord } } 972 | \sb 973 | { 974 | \__deriv_insert_mskip:nn {#4} { inf_var } 975 | \__deriv_insert_var:Nnnn \l__deriv_tmpb_tl {##2} {#4} {#5} 976 | } 977 | \int_compare:nNnF {##1} = { \l__deriv_var_count_int } 978 | { \__deriv_insert_mskip:nn {#4} { var_inf } } 979 | } 980 | } 981 | } 982 | %%%%% And the rest of the code %%%%% 983 | % variant 984 | \cs_new:Npn \__deriv_insert_numinf:n #1 985 | { \__deriv_insert_inf:nn {#1} { _num } } 986 | % variant 987 | \cs_new:Npn \__deriv_insert_deninf:n #1 988 | { \__deriv_insert_inf:nn {#1} { _den } } 989 | % variant, name 990 | \cs_new:Npn \__deriv_insert_inf:nn #1 #2 991 | { \exp_not:v { l__deriv_#1_style_inf#2_tl } } 992 | % dv, function, muskip 993 | \cs_new:Npn \__deriv_insert_fun:nnn #1 #2 #3 994 | { 995 | \tl_if_blank:nF {#2} 996 | { 997 | \__deriv_insert_mskip:nn {#1} {#3} 998 | \bool_if:cTF { l__deriv_#1_misc_fun_bool } 999 | { \__deriv_add_delims:nnn {#1} { fun } {#2} } 1000 | {#2} 1001 | } 1002 | } 1003 | % if delim, variable, variant, if star 1004 | \cs_new:Npn \__deriv_insert_var:Nnnn #1 #2 #3 #4 1005 | { 1006 | \bool_if:NTF #1 1007 | { \__deriv_add_delims:nnn {#3} { var#4 } {#2} } 1008 | { \__deriv_handle_double_sp:n {#2} } 1009 | } 1010 | % if delim, variable, variant 1011 | \cs_new:Npn \__deriv_insert_var:Nnn #1 #2 #3 1012 | { 1013 | \bool_if:NTF #1 1014 | { \__deriv_add_delims:nnn {#3} { var } {#2} } 1015 | { \__deriv_handle_double_sp:n {#2} } 1016 | } 1017 | % order, variant, name 1018 | \cs_new:Npn \__deriv_insert_ord:Nnn #1 #2 #3 1019 | { 1020 | \sp 1021 | { 1022 | \__deriv_insert_mskip:nn {#2} {#3} 1023 | \exp_not:V #1 1024 | } 1025 | } 1026 | % dv, name 1027 | \cs_new:Npn \__deriv_insert_mskip:nn #1 #2 1028 | { \exp_not:v { l__deriv_#1_sep_#2_tl } } 1029 | 1030 | %%%%% Scale, delimiters, evaluation %%%%% 1031 | % variable 1032 | \cs_new:Npn \__deriv_handle_double_sp:n #1 1033 | { 1034 | \str_case_e:nnF { ^ } 1035 | { 1036 | { \tl_item:nn {#1} { -2 } } { \exp_not:n { {#1} } } 1037 | { \tl_item:nn {#1} { -4 } } { \exp_not:n { {#1} } } 1038 | } 1039 | { \exp_not:n {#1} } 1040 | } 1041 | % dv, code-for-fraction 1042 | \cs_new:Npn \__deriv_fraction:nn #1 #2 1043 | { 1044 | \bool_if:cTF { l__deriv_#1_misc_frac_bool } 1045 | { \__deriv_add_delims:nnn {#1} { frac } {#2} } 1046 | {#2} 1047 | } 1048 | % dv, code-for-fraction 1049 | \cs_new:Npn \__deriv_fraction_slash:nn #1 #2 1050 | { 1051 | \bool_if:cTF { l__deriv_#1_misc_frac_bool } 1052 | { \__deriv_add_delims:nnn {#1} { frac_slash } {#2} } 1053 | {#2} 1054 | } 1055 | % dv, sub, sup, code-for-fraction 1056 | \cs_new:Npn \__deriv_evaluation:nnnn #1 #2 #3 #4 1057 | { 1058 | \__deriv_if_value:nTF {#2} 1059 | { 1060 | \__deriv_add_delims:nnn {#1} { eval } {#4} 1061 | \sb{ \__deriv_insert_mskip:nn {#1} { eval_sb } #2 } 1062 | \__deriv_if_value:nT {#3} 1063 | { \sp{ \__deriv_insert_mskip:nn {#1} { eval_sp } #3 } } 1064 | } 1065 | { 1066 | \__deriv_if_value:nTF {#3} 1067 | { 1068 | \__deriv_add_delims:nnn {#1} { eval } {#4} 1069 | \sp{ \__deriv_insert_mskip:nn {#1} { eval_sp } #3 } 1070 | } 1071 | {#4} 1072 | } 1073 | } 1074 | % dv, sub, sup, code-for-fraction 1075 | \cs_new:Npn \__deriv_evaluation_slash:nnnn #1 #2 #3 #4 1076 | { 1077 | \__deriv_if_value:nTF {#2} 1078 | { 1079 | \__deriv_add_delims:nnn {#1} { eval_slash } {#4} 1080 | \sb{ \__deriv_insert_mskip:nn {#1} { eval_sb } #2 } 1081 | \__deriv_if_value:nT {#3} 1082 | { \sp{ \__deriv_insert_mskip:nn {#1} { eval_sp } #3 } } 1083 | } 1084 | { 1085 | \__deriv_if_value:nTF {#3} 1086 | { 1087 | \__deriv_add_delims:nnn {#1} { eval_slash } {#4} 1088 | \sp{ \__deriv_insert_mskip:nn {#1} { eval_sp } #3 } 1089 | } 1090 | {#4} 1091 | } 1092 | } 1093 | % dv, sub, sup, code-for-fraction 1094 | \cs_new:Npn \__deriv_evaluation_compact:nnnn #1 #2 #3 #4 1095 | { 1096 | \__deriv_if_value:nTF {#2} 1097 | { 1098 | \__deriv_add_delims:nnn {#1} { eval_compact } {#4} 1099 | \sb{ \__deriv_insert_mskip:nn {#1} { eval_sb } #2 } 1100 | \__deriv_if_value:nT {#3} 1101 | { \sp{ \__deriv_insert_mskip:nn {#1} { eval_sp } #3 } } 1102 | } 1103 | { 1104 | \__deriv_if_value:nTF {#3} 1105 | { 1106 | \__deriv_add_delims:nnn {#1} { eval_compact } {#4} 1107 | \sp{ \__deriv_insert_mskip:nn {#1} { eval_sp } #3 } 1108 | } 1109 | {#4} 1110 | } 1111 | } 1112 | % dv, name, value 1113 | \cs_new:Npn \__deriv_add_delims:nnn #1 #2 #3 1114 | { \tl_use:c { l__deriv_#1_scale_#2_tl } {#1} {#2} {#3} } 1115 | % dv, name, code 1116 | \cs_new:Npn \__deriv_scale_auto:nnn #1 #2 #3 1117 | { 1118 | \__deriv_auto_left:n \tl_item:cn { l__deriv_#1_delims_#2_tl } { 1 } 1119 | #3 1120 | \__deriv_auto_right:n \tl_item:cn { l__deriv_#1_delims_#2_tl } { 2 } 1121 | } 1122 | % dv, name, code 1123 | \cs_new:Npn \__deriv_scale_none:nnn #1 #2 #3 1124 | { 1125 | \__deriv_dont_use_dot:x { \tl_item:cn { l__deriv_#1_delims_#2_tl } { 1 } } 1126 | #3 1127 | \__deriv_dont_use_dot:x { \tl_item:cn { l__deriv_#1_delims_#2_tl } { 2 } } 1128 | } 1129 | % item 1130 | \cs_new:Npn \__deriv_dont_use_dot:n #1 1131 | { \str_if_eq:nnF {#1} { . } {#1} } 1132 | % dv, name, code 1133 | \cs_new:Npn \__deriv_scale_big:nnnn #1 #2 #3 #4 1134 | { \__deriv_scale_big_auxi:ncn {#1} { l__deriv_#2_delims_#3_tl } {#4} } 1135 | % scaling, delims, code 1136 | \cs_new:Npn \__deriv_scale_big_auxi:nNn #1 #2 #3 1137 | { 1138 | \tl_use:c { #1 l } { \tl_item:Nn #2 { 1 } } 1139 | #3 1140 | \tl_use:c { #1 r } { \tl_item:Nn #2 { 2 } } 1141 | } 1142 | %%%%% Calculation of mixed order %%%%% 1143 | % mixed-order-tl, order-seq, variant 1144 | \cs_new:Npn \__deriv_mixed_order:NNn #1 #2 #3 1145 | { 1146 | \__deriv_replace:NN \l__deriv_input_seq #2 1147 | \__deriv_seq_counting:NNNn \l__deriv_symbol_seq \l__deriv_number_seq \l__deriv_input_seq {#3} 1148 | \__deriv_sort:NNNn \l__deriv_permutation_seq \l__deriv_symbol_seq \l__deriv_number_seq {#3} 1149 | \__deriv_combine_seq:NNNNn \l__deriv_sorted_seq \l__deriv_permutation_seq \l__deriv_symbol_seq \l__deriv_number_seq {#3} 1150 | \__deriv_output:NNNn #1 \l__deriv_sorted_seq \l__deriv_numerical_tl {#3} 1151 | } 1152 | % input-seq, order-seq 1153 | \cs_new_protected:Npn \__deriv_replace:NN #1 #2 1154 | { 1155 | \tl_set:Nf \l__deriv_input_tl { \seq_use:Nn #2 { , } } 1156 | \tl_remove_all:Nn \l__deriv_input_tl { ~ } 1157 | \tl_replace_all:Nnn \l__deriv_input_tl { -- } { , } 1158 | \tl_replace_all:Nnn \l__deriv_input_tl { - } { ,- } 1159 | \tl_replace_all:Nnn \l__deriv_input_tl { + } { , } 1160 | 1161 | \seq_set_split:NnV #1 { , } \l__deriv_input_tl 1162 | \seq_remove_all:Nn #1 {} 1163 | } 1164 | 1165 | % symbol-seq, number-seq, input-seq 1166 | \cs_new_protected:Npn \__deriv_seq_counting:NNNn #1 #2 #3 #4 1167 | { \__deriv_seq_counting:NNNNNNNn #1 #2 #3 \l__deriv_sym_tmpa_seq \l__deriv_sym_tmpb_seq \l__deriv_num_tmpa_seq \l__deriv_num_tmpb_seq {#4} } 1168 | 1169 | \cs_new_protected:Npn \__deriv_seq_counting:NNNNNNNn #1 #2 #3 #4 #5 #6 #7 #8 1170 | { 1171 | \seq_clear:N #1 1172 | \seq_clear:N #2 1173 | \seq_clear:N #4 1174 | \seq_clear:N #5 1175 | \seq_clear:N #6 1176 | \seq_clear:N #7 1177 | \tl_clear:N \l__deriv_numerical_tl 1178 | 1179 | \seq_map_inline:Nn #3 1180 | { 1181 | \str_if_in:nnTF {##1} / 1182 | { \__deriv_extract_frac:NNNNw \l__deriv_sym_tmpa_tl \l__deriv_sym_tmpb_tl \l__deriv_num_tmpa_tl \l__deriv_num_tmpb_tl ##1 \q_stop } 1183 | { 1184 | \__deriv_extract:NNn \l__deriv_sym_tmpa_tl \l__deriv_num_tmpa_tl {##1} 1185 | \tl_clear:N \l__deriv_sym_tmpb_tl 1186 | \tl_set:Nn \l__deriv_num_tmpb_tl { 1 } 1187 | } 1188 | 1189 | \__deriv_if_in_two_seq:NNNNTF #4 #5 \l__deriv_sym_tmpa_tl \l__deriv_sym_tmpb_tl 1190 | { \__deriv_update_seq:NNNNV #6 #7 \l__deriv_num_tmpa_tl \l__deriv_num_tmpb_tl \l__deriv_seq_pos_int } 1191 | { 1192 | \__deriv_add_to_seq:NNVV #4 #6 \l__deriv_sym_tmpa_tl \l__deriv_num_tmpa_tl 1193 | \__deriv_add_to_seq:NNVV #5 #7 \l__deriv_sym_tmpb_tl \l__deriv_num_tmpb_tl 1194 | } 1195 | } 1196 | \__deriv_combine_frac:NNNNNNn #1 #2 #4 #5 #6 #7 {#8} 1197 | } 1198 | % sym-tl, num-tl, seq-item 1199 | \cs_new_protected:Npn \__deriv_extract:NNn #1 #2 #3 1200 | { 1201 | \int_zero:N \l__deriv_tmpa_int 1202 | \tl_map_inline:nn {#3} 1203 | { 1204 | \tl_if_in:NnTF \c__deriv_digits_tl {##1} 1205 | { \int_incr:N \l__deriv_tmpa_int } 1206 | { \tl_map_break: } 1207 | } 1208 | 1209 | \tl_set:Nx #2 { \tl_range:nnn {#3} { 1 } \l__deriv_tmpa_int } 1210 | \int_incr:N \l__deriv_tmpa_int 1211 | \tl_set:Nx #1 { \tl_range:nnn {#3} \l__deriv_tmpa_int { -1 } } 1212 | 1213 | \exp_args:NV \str_case:nn #2 1214 | { 1215 | { } { \tl_set:Nn #2 { 1 } } 1216 | { - } { \tl_set:Nn #2 { -1 } } 1217 | } 1218 | } 1219 | 1220 | \cs_new_protected:Npn \__deriv_extract_frac:NNNNw #1 #2 #3 #4 #5 / #6 \q_stop 1221 | { 1222 | %TODO: Strip parentheses from denominator (second line) to allow input like '1/(2m)' and would be similar to writing '1/2m'. 1223 | % However, terms like '1/(m+n)' and '1/(2m+n)' are different and the latter must not be interpreted as '1/(2m+2n)' 1224 | % Currently '1/2m' is being interpreted as '1/(2m)' but technically 'm/2' is the correct way. And should ideally be changed - but not a must right now. 1225 | %TODO: Make code to handle the case '(m+n)/xxx' as input correctly with a loop i.e. as 'm/xxx + m/xxx'. Likely has to be done in \deriv_input:nn 1226 | \__deriv_extract:NNn #1 #3 {#5} 1227 | 1228 | %TODO: Temporary solution to: Strip pearentheses from denominator 1229 | \str_if_in:nnTF {#6} ( 1230 | { 1231 | \str_if_in:nnTF {#6} ) 1232 | { \__deriv_extract_parenthesis:NNw #2 #4 #6 \q_stop } 1233 | { \__deriv_extract:NNn #2 #4 {#6} } 1234 | } 1235 | { \__deriv_extract:NNn #2 #4 {#6} } 1236 | 1237 | \tl_if_eq:NNT #1 #2 1238 | { 1239 | \tl_clear:N #1 1240 | \tl_clear:N #2 1241 | } 1242 | } 1243 | 1244 | \cs_new_protected:Npn \__deriv_extract_parenthesis:NNw #1 #2 ( #3 ) \q_stop 1245 | { \__deriv_extract:NNn #1 #2 {#3} } 1246 | 1247 | \cs_new:Npn \__deriv_combine_frac:NNNNNNn #1 #2 #3 #4 #5 #6 #7 1248 | { 1249 | \int_step_inline:nn { \seq_count:N #3 } 1250 | { 1251 | \tl_set:Nx \l__deriv_tmpa_tl { \seq_item:Nn #3 {##1} } 1252 | \tl_set:Nx \l__deriv_tmpb_tl { \seq_item:Nn #4 {##1} } 1253 | \int_set:Nn \l__deriv_tmpa_int { \seq_item:Nn #5 {##1} } 1254 | \int_set:Nn \l__deriv_tmpb_int { \seq_item:Nn #6 {##1} } 1255 | 1256 | \int_compare:nNnF \l__deriv_tmpa_int = 0 1257 | { 1258 | \__deriv_adjust_frac_integers:NN \l__deriv_tmpa_int \l__deriv_tmpb_int 1259 | 1260 | \__deriv_add_frac_to_seq:NNVVVVn #1 #2 \l__deriv_tmpa_tl \l__deriv_tmpb_tl \l__deriv_tmpa_int \l__deriv_tmpb_int {#7} 1261 | } 1262 | } 1263 | } 1264 | 1265 | \cs_new:Npn \__deriv_adjust_frac_integers:NN #1 #2 1266 | { 1267 | \int_compare:nNnTF #1 = #2 1268 | { 1269 | \int_set:Nn #1 { 1 } 1270 | \int_set:Nn #2 { 1 } 1271 | } 1272 | { 1273 | \int_compare:nNnT \l__deriv_tmpb_int < 0 1274 | { 1275 | \int_set:Nn #1 { -1*#1 } 1276 | \int_set:Nn #2 { -1*#2 } 1277 | } 1278 | \deriv_gcd:NN #1 #2 1279 | } 1280 | } 1281 | % sym-tl, num-tl 1282 | \cs_new_protected:Npn \__deriv_add_frac_to_seq:NNnnnnn #1 #2 #3 #4 #5 #6 #7 1283 | { 1284 | \tl_if_empty:nTF {#3} 1285 | { 1286 | \tl_if_empty:nTF {#4} 1287 | { 1288 | \str_if_eq:vnTF { l__deriv_#7_sort_numerical_tl } { symbolic } 1289 | { 1290 | \int_compare:nNnTF {#6} = 1 1291 | { \__deriv_add_to_seq:NNnn #1 #2 { } {#5} } 1292 | { \__deriv_add_to_seq:NNnn #1 #2 { /#6 } {#5} } 1293 | } 1294 | { 1295 | \int_compare:nNnTF {#6} = 1 1296 | { \tl_set:Nn \l__deriv_numerical_tl {#5} } 1297 | { \tl_set:Nn \l__deriv_numerical_tl { #5/#6 } } 1298 | } 1299 | } 1300 | { 1301 | \int_compare:nNnTF {#6} = 1 1302 | { \__deriv_add_to_seq:NNnn #1 #2 { /#4 } {#5} } 1303 | { \__deriv_add_to_seq:NNnn #1 #2 { /(#6#4) } {#5} } 1304 | } 1305 | } 1306 | { 1307 | \tl_if_empty:nTF {#4} 1308 | { 1309 | \int_compare:nNnTF {#6} = 1 1310 | { \__deriv_add_to_seq:NNnn #1 #2 {#3} {#5} } 1311 | { \__deriv_add_to_seq:NNnn #1 #2 { #3/#6 } {#5} } 1312 | } 1313 | { 1314 | \int_compare:nNnTF {#6} = 1 1315 | { \__deriv_add_to_seq:NNnn #1 #2 { #3/#4 } {#5} } 1316 | { \__deriv_add_to_seq:NNnn #1 #2 { #3/(#6#4) } {#5} } 1317 | } 1318 | } 1319 | } 1320 | 1321 | % sym-tl, num-tl 1322 | \cs_new_protected:Npn \__deriv_add_to_seq:NNnn #1 #2 #3 #4 1323 | { 1324 | \seq_put_right:Nn #1 {#3} 1325 | \seq_put_right:Nn #2 {#4} 1326 | } 1327 | % sym-tl, num-tl 1328 | \cs_new_protected:Npn \__deriv_update_seq:NNnn #1 #2 #3 #4 1329 | { 1330 | \seq_map_indexed_inline:Nn #1 1331 | { 1332 | \tl_if_eq:nnT {#3} {##2} 1333 | { 1334 | \exp_args:NNnx 1335 | \seq_set_item:Nnn #2 {##1} { \int_eval:n { \seq_item:Nn #2 {##1} + #4 } } 1336 | \seq_map_break: 1337 | } 1338 | } 1339 | } 1340 | 1341 | \cs_new_protected:Npn \__deriv_find_in_seq:NNn #1 #2 #3 1342 | { 1343 | \int_zero:N #2 1344 | \seq_map_indexed_inline:Nn #1 1345 | { \tl_if_eq:nnT {#3} {##2} { \seq_map_break:n { \int_set:Nn #2 {##1} } } } 1346 | } 1347 | 1348 | \cs_set_eq:NN \__deriv_update_seq:Nnn \seq_set_item:Nnn 1349 | \cs_generate_variant:Nn \__deriv_update_seq:Nnn { NVV } 1350 | 1351 | \cs_new_protected:Npn \__deriv_update_seq:NNNNn #1 #2 #3 #4 #5 1352 | { \__deriv_addfrac:NNVVxxn #1 #2 #3 #4 { \seq_item:Nn #1 {#5} } { \seq_item:Nn #2 {#5} } {#5} } 1353 | 1354 | \cs_new:Npn \__deriv_addfrac:NNnnnnn #1 #2 #3 #4 #5 #6 #7 1355 | { 1356 | \exp_args:NNnx \seq_set_item:Nnn #1 {#7} { \int_eval:n { #3*#6 + #4*#5 } } 1357 | \exp_args:NNnx \seq_set_item:Nnn #2 {#7} { \int_eval:n { #4*#6 } } 1358 | } 1359 | % sorted-seq, permutation-seq, symbol-seq, number-seq, variant 1360 | \cs_new:Npn \__deriv_combine_seq:NNNNn #1 #2 #3 #4 #5 1361 | { 1362 | \seq_clear:N #1 1363 | \seq_map_inline:Nn #2 1364 | { 1365 | \tl_set:Nx \l__deriv_sym_tmpa_tl { \seq_item:Nn #3 {##1} } 1366 | \tl_set:Nx \l__deriv_num_tmpa_tl { \seq_item:Nn #4 {##1} } 1367 | \__deriv_eval_term:NVVn #1 \l__deriv_sym_tmpa_tl \l__deriv_num_tmpa_tl {#5} 1368 | } 1369 | } 1370 | % sorted-seq, sym-tl, num-tl, variant 1371 | \cs_new_protected:Npn \__deriv_eval_term:Nnnn #1 #2 #3 #4 1372 | { 1373 | \tl_if_empty:nTF {#2} 1374 | { \seq_put_right:Nn #1 {#3} } 1375 | { 1376 | \tl_if_head_eq_charcode:nNTF {#2} / 1377 | { \seq_put_right:Nn #1 {#3#2} } 1378 | { 1379 | \int_compare:nNnTF {#3} = { 1 } 1380 | { \seq_put_right:Nn #1 {#2} } 1381 | { 1382 | \int_compare:nNnTF {#3} = { 0 } 1383 | { \prg_do_nothing: } 1384 | { 1385 | \int_compare:nNnTF {#3} = { -1 } 1386 | { \seq_put_right:Nn #1 { -#2 } } 1387 | { \seq_put_right:Nn #1 {#3#2} } 1388 | } 1389 | } 1390 | } 1391 | } 1392 | } 1393 | % permutation-seq, symbol-seq, number-seq, variant 1394 | \cs_new_protected:Npn \__deriv_sort:NNNn #1 #2 #3 #4 1395 | { 1396 | \seq_clear:N #1 1397 | \int_step_inline:nn { \seq_count:N #2 } 1398 | { \seq_put_right:Nn #1 {##1} } 1399 | 1400 | \bool_if:cT { l__deriv_#4_switch_sort_bool } 1401 | { 1402 | \int_set:Nn \l__deriv_sort_max_int { \seq_count:c { l__deriv_#4_sort_method_seq } } 1403 | \seq_sort:Nn #1 1404 | { 1405 | \tl_set:Nx \l__deriv_sym_tmpa_tl { \seq_item:Nn #2 {##1} } 1406 | \tl_set:Nx \l__deriv_sym_tmpb_tl { \seq_item:Nn #2 {##2} } 1407 | \tl_set:Nx \l__deriv_num_tmpa_tl { \seq_item:Nn #3 {##1} } 1408 | \tl_set:Nx \l__deriv_num_tmpb_tl { \seq_item:Nn #3 {##2} } 1409 | 1410 | \__deriv_sort_method:cn { l__deriv_#4_sort_method_seq } {#4} 1411 | } 1412 | } 1413 | } 1414 | % method-seq, dv 1415 | \cs_new_protected:Npn \__deriv_sort_method:Nn #1 #2 1416 | { 1417 | \seq_map_indexed_inline:Nn #1 1418 | { 1419 | ##2 {#2} 1420 | \int_compare:nNnT {##1} = { \l__deriv_sort_max_int } 1421 | { \seq_map_break:n { \sort_return_same: } } 1422 | } 1423 | } 1424 | % dv 1425 | \cs_new_protected:Npn \__deriv_sort_sign:n #1 1426 | { 1427 | \tl_if_head_eq_charcode:VNTF \l__deriv_num_tmpb_tl - 1428 | { 1429 | \tl_if_head_eq_charcode:VNF \l__deriv_num_tmpa_tl - 1430 | { \__deriv_sort_reverse:Nnn \c_false_bool {#1} { sign } } 1431 | } 1432 | { 1433 | \tl_if_head_eq_charcode:VNT \l__deriv_num_tmpa_tl - 1434 | { \__deriv_sort_reverse:Nnn \c_true_bool {#1} { sign } } 1435 | } 1436 | } 1437 | % dv 1438 | \cs_new_protected:Npn \__deriv_sort_symbol:n #1 1439 | { 1440 | \int_set:Nn \l__deriv_tmpa_int { \tl_count:N \l__deriv_sym_tmpa_tl } 1441 | \int_set:Nn \l__deriv_tmpb_int { \tl_count:N \l__deriv_sym_tmpb_tl } 1442 | 1443 | \int_compare:nNnTF \l__deriv_tmpa_int > \l__deriv_tmpb_int 1444 | { \__deriv_sort_reverse:Nnn \c_false_bool {#1} { symbol } } 1445 | { 1446 | \int_compare:nNnT \l__deriv_tmpa_int < \l__deriv_tmpb_int 1447 | { \__deriv_sort_reverse:Nnn \c_true_bool {#1} { symbol } } 1448 | } 1449 | } 1450 | % dv 1451 | \cs_new_protected:Npn \__deriv_sort_lexical:n #1 1452 | { \__deriv_sort_lexical_auxi:VVn \l__deriv_sym_tmpa_tl \l__deriv_sym_tmpb_tl {#1} } 1453 | % symbol-str-1, symbol-str-2, dv 1454 | \cs_new_protected:Npn \__deriv_sort_lexical_auxi:nnn #1 #2 #3 1455 | { 1456 | \str_compare:nNnTF {#1} < {#2} 1457 | { \__deriv_sort_reverse:Nnn \c_false_bool {#3} { lexical } } 1458 | { 1459 | \str_compare:nNnT {#1} > {#2} 1460 | { \__deriv_sort_reverse:Nnn \c_true_bool {#3} { lexical } } 1461 | } 1462 | } 1463 | % dv 1464 | \cs_new_protected:Npn \__deriv_sort_abs:n #1 1465 | { 1466 | \int_set:Nn \l__deriv_tmpa_int { \int_abs:n \l__deriv_num_tmpa_tl } 1467 | \int_set:Nn \l__deriv_tmpb_int { \int_abs:n \l__deriv_num_tmpb_tl } 1468 | 1469 | \int_compare:nNnTF \l__deriv_tmpa_int > \l__deriv_tmpb_int 1470 | { \__deriv_sort_reverse:Nnn \c_false_bool {#1} { abs } } 1471 | { 1472 | \int_compare:nNnT \l__deriv_tmpa_int < \l__deriv_tmpb_int 1473 | { \__deriv_sort_reverse:Nnn \c_true_bool {#1} { abs } } 1474 | } 1475 | } 1476 | % dv 1477 | \cs_new_protected:Npn \__deriv_sort_number:n #1 1478 | { 1479 | \int_compare:nNnTF \l__deriv_num_tmpa_tl > \l__deriv_num_tmpb_tl 1480 | { \__deriv_sort_reverse:Nnn \c_false_bool {#1} { number } } 1481 | { 1482 | \int_compare:nNnT \l__deriv_num_tmpa_tl < \l__deriv_num_tmpb_tl 1483 | { \__deriv_sort_reverse:Nnn \c_true_bool {#1} { number } } 1484 | } 1485 | } 1486 | % true/false, dv, sort-method 1487 | \cs_new_protected:Npn \__deriv_sort_reverse:Nnn #1 #2 #3 1488 | { 1489 | \exp_args:NNc 1490 | \bool_xor:nnTF #1 { l__deriv_#2_sort_#3_reverse_bool } 1491 | { \seq_map_break:n { \sort_return_swapped: } } 1492 | { \seq_map_break:n { \sort_return_same: } } 1493 | } 1494 | % mixed-order-tl, sorted-seq, numerical-term, variant 1495 | \cs_new_protected:Npn \__deriv_output:NNNn #1 #2 #3 #4 1496 | { 1497 | \tl_set:Nf #1 { \seq_use:Nn #2 { + } } 1498 | 1499 | \tl_if_empty:NF #3 1500 | { 1501 | \tl_if_empty:NTF #1 1502 | { \tl_put_left:NV #1 #3 } 1503 | { 1504 | \exp_args:Nv \str_case:nnF { l__deriv_#4_sort_numerical_tl } 1505 | { 1506 | { last } { \tl_put_right:Nx #1 { + #3 } } 1507 | { first } { \tl_put_left:Nx #1 { #3 + } } 1508 | } 1509 | { 1510 | \tl_if_head_eq_charcode:VNTF #1 - 1511 | { \tl_put_left:NV #1 #3 } 1512 | { \tl_put_right:Nx #1 { + #3 } } 1513 | } 1514 | } 1515 | } 1516 | \tl_replace_all:Nnn #1 { +- } { - } 1517 | \tl_if_empty:NT #1 { \tl_set:Nn #1 { 0 } } 1518 | } 1519 | 1520 | %%%%% GCD (Greatest Common Divisor) %%%%% 1521 | 1522 | \cs_new:Npn \deriv_binary_shift_left:Nn #1 #2 1523 | { 1524 | \tl_set:Nx #1 1525 | { 1526 | \tl_range:Nnn #1 { #2+1 } { -1 } 1527 | \prg_replicate:nn {#2} { 0 } 1528 | } 1529 | } 1530 | \cs_new:Npn \deriv_binary_shift_right:N #1 1531 | { \tl_set:Nx #1 { 0 \tl_range:Nnn #1 { 1 } { -2 } } } 1532 | 1533 | \prg_new_conditional:Npnn \deriv_binary_if_even:N #1 { p } 1534 | { 1535 | \str_if_eq:eeTF { \tl_item:Nn #1 { -1 } } { 0 } 1536 | { \prg_return_true: } 1537 | { \prg_return_false: } 1538 | } 1539 | 1540 | \cs_new:Npn \deriv_gcd:NN #1 #2 1541 | { 1542 | % Not needed in my use case but technically correct to include 1543 | %\int_compare:nNnTF #1 = 0 1544 | %{ \int_set:Nn #2 { \int_sign:n {#2} } } 1545 | %{ 1546 | \int_compare:nNnTF #2 = 0 1547 | { \int_set:Nn #1 { \int_sign:n {#1} } } 1548 | { 1549 | \tl_set:Nx \l__deriv_gcd_result_tl { \int_to_bin:n { \int_abs:n #1 } } 1550 | \tl_set:Nx \l__deriv_gcd_remain_tl { \int_to_bin:n { \int_abs:n #2 } } 1551 | 1552 | \__deriv_gcd:NN \l__deriv_gcd_result_tl \l__deriv_gcd_remain_tl 1553 | 1554 | \int_set:Nn #1 { #1 / \l__deriv_gcd_result_tl } 1555 | \int_set:Nn #2 { #2 / \l__deriv_gcd_result_tl } 1556 | } 1557 | %} 1558 | } 1559 | 1560 | \cs_new:Npn \__deriv_gcd:NN #1 #2 1561 | { 1562 | \int_zero:N \l__deriv_gcd_counter_int 1563 | \bool_while_do:nn { \deriv_binary_if_even_p:N #1 && \deriv_binary_if_even_p:N #2 } 1564 | { 1565 | \deriv_binary_shift_right:N #1 1566 | \deriv_binary_shift_right:N #2 1567 | \int_incr:N \l__deriv_gcd_counter_int 1568 | } 1569 | 1570 | \bool_while_do:nn { \deriv_binary_if_even_p:N #1 } 1571 | { \deriv_binary_shift_right:N #1 } 1572 | 1573 | \bool_until_do:nn { \int_compare_p:nNn #2 = 0 } 1574 | { 1575 | \bool_while_do:nn { \deriv_binary_if_even_p:N #2 } 1576 | { \deriv_binary_shift_right:N #2 } 1577 | 1578 | \__deriv_gcd_swap_helper:NNff #1 #2 { \exp_args:NV \int_from_bin:n {#1} } { \exp_args:NV \int_from_bin:n {#2} } 1579 | } 1580 | \deriv_binary_shift_left:NV #1 \l__deriv_gcd_counter_int 1581 | \tl_set:Nx #1 { \exp_args:NV \int_from_bin:n {#1} } 1582 | } 1583 | \cs_new:Npn \__deriv_gcd_swap_helper:NNnn #1 #2 #3 #4 1584 | { 1585 | \int_compare:nNnTF {#3} > {#4} 1586 | { 1587 | \tl_set_eq:NN #1 #2 1588 | \tl_set:Nx #2 { \int_to_bin:n { #3 - #4 } } 1589 | } 1590 | { \tl_set:Nx #2 { \int_to_bin:n { #4 - #3 } } } 1591 | } 1592 | %%%%% Declaring Variant %%%%% 1593 | 1594 | \DeclareDocumentCommand{\NewDerivative}{ m m o } 1595 | { 1596 | \cs_if_exist:NTF #1 1597 | { 1598 | \msg_error:nnxx { deriv } { command-already-defined } 1599 | { \token_to_str:N #1 } 1600 | { \token_to_str:N \NewDerivative } 1601 | } 1602 | { 1603 | \deriv_preamble:NNnnn \l__deriv_cs_name_tl #1 {#2} {#3} { dv } 1604 | \deriv_dv_define:NVn \NewDocumentCommand \l__deriv_cs_name_tl {#1} 1605 | } 1606 | } 1607 | 1608 | \DeclareDocumentCommand{\RenewDerivative}{ m m o } 1609 | { 1610 | \cs_if_exist:NTF #1 1611 | { 1612 | \deriv_preamble:NNnnn \l__deriv_cs_name_tl #1 {#2} {#3} { dv } 1613 | \deriv_dv_define:NVn \RenewDocumentCommand \l__deriv_cs_name_tl {#1} 1614 | } 1615 | { 1616 | \msg_error:nnxx { deriv } { command-not-defined } 1617 | { \token_to_str:N #1 } 1618 | { \token_to_str:N \RenewDerivative } 1619 | } 1620 | } 1621 | 1622 | \DeclareDocumentCommand{\ProvideDerivative}{ m m o } 1623 | { 1624 | \cs_if_exist:NF #1 1625 | { 1626 | \deriv_preamble:NNnnn \l__deriv_cs_name_tl #1 {#2} {#3} { dv } 1627 | \deriv_dv_define:NVn \ProvideDocumentCommand \l__deriv_cs_name_tl {#1} 1628 | } 1629 | } 1630 | 1631 | \DeclareDocumentCommand{\DeclareDerivative}{ m m o } 1632 | { 1633 | \deriv_preamble:NNnnn \l__deriv_cs_name_tl #1 {#2} {#3} { dv } 1634 | \deriv_dv_define:NVn \DeclareDocumentCommand \l__deriv_cs_name_tl {#1} 1635 | } 1636 | 1637 | \DeclareDocumentCommand{\NewDifferential}{ m m o } 1638 | { 1639 | \cs_if_exist:NTF #1 1640 | { 1641 | \msg_error:nnxx { deriv } { command-already-defined } 1642 | { \token_to_str:N #1 } 1643 | { \token_to_str:N \NewOdvVariant } 1644 | } 1645 | { 1646 | \deriv_preamble:NNnnn \l__deriv_dv_tmp_tl #1 {#2} {#3} { i } 1647 | \deriv_i_define:NVn \NewDocumentCommand \l__deriv_dv_tmp_tl {#1} 1648 | } 1649 | } 1650 | 1651 | \DeclareDocumentCommand{\RenewDifferential}{ m m o } 1652 | { 1653 | \cs_if_exist:NTF #1 1654 | { 1655 | \deriv_preamble:NNnnn \l__deriv_dv_tmp_tl #1 {#2} {#3} { i } 1656 | \deriv_i_define:NVn \RenewDocumentCommand \l__deriv_dv_tmp_tl {#1} 1657 | } 1658 | { 1659 | \msg_error:nnxx { deriv } { command-not-defined } 1660 | { \token_to_str:N #1 } 1661 | { \token_to_str:N \RenewOdvVariant } 1662 | } 1663 | } 1664 | 1665 | \DeclareDocumentCommand{\ProvideDifferential}{ m m o } 1666 | { 1667 | \cs_if_exist:NF #1 1668 | { 1669 | \deriv_preamble:NNnnn \l__deriv_dv_tmp_tl #1 {#2} {#3} { i } 1670 | \deriv_i_define:NVn \ProvideDocumentCommand \l__deriv_dv_tmp_tl {#1} 1671 | } 1672 | } 1673 | 1674 | \DeclareDocumentCommand{\DeclareDifferential}{ m m o } 1675 | { 1676 | \deriv_preamble:NNnnn \l__deriv_dv_tmp_tl #1 {#2} {#3} { i } 1677 | \deriv_i_define:NVn \DeclareDocumentCommand \l__deriv_dv_tmp_tl {#1} 1678 | } 1679 | 1680 | %%%%% slash frac %%%%% 1681 | 1682 | \DeclareDocumentCommand{\slashfrac}{ o m m } 1683 | { 1684 | \group_begin: 1685 | \tl_if_novalue:nTF {#1} 1686 | { \__deriv_slashfrac_auto:nn {#2} {#3} } 1687 | { 1688 | \str_case:nnF {#1} 1689 | { 1690 | { auto } { \__deriv_slashfrac_auto:nn {#2} {#3} } 1691 | { none } { \__deriv_slashfrac_none:nn {#2} {#3} } 1692 | } 1693 | { \__deriv_slashfrac_scale:nnn {#1} {#2} {#3} } 1694 | } 1695 | \group_end: 1696 | } 1697 | % numerator, denominator 1698 | \cs_new_protected:Npn \__deriv_slashfrac_auto:nn #1 #2 1699 | { 1700 | \__deriv_auto_left:n . 1701 | {#1} \middle/ {#2} 1702 | \__deriv_auto_right:n . 1703 | } 1704 | % numerator, denominator 1705 | \cs_new_protected:Npn \__deriv_slashfrac_none:nn #1 #2 1706 | { {#1} / {#2} } 1707 | % scale, numerator, denominator 1708 | \cs_new_protected:Npn \__deriv_slashfrac_scale:nnn #1 #2 #3 1709 | { 1710 | \use:c { #1 l } . 1711 | {#2} 1712 | \use:c {#1} / 1713 | {#3} 1714 | \use:c { #1 r } . 1715 | } 1716 | 1717 | %%%%% Generate variants %%%%% 1718 | 1719 | \prg_generate_conditional_variant:Nnn \__deriv_show_order:N { c } { T, TF } 1720 | 1721 | \cs_generate_variant:Nn \__deriv_set_rubber_length:Nn { c } 1722 | \cs_generate_variant:Nn \deriv_dv_define:Nnn { NV } 1723 | \cs_generate_variant:Nn \deriv_i_define:Nnn { NV } 1724 | \cs_generate_variant:Nn \deriv_set_keys:nn { V } 1725 | \cs_generate_variant:Nn \__deriv_dont_use_dot:n { x } 1726 | \cs_generate_variant:Nn \__deriv_scale_big_auxi:nNn { nc } 1727 | 1728 | \cs_generate_variant:Nn \__deriv_insert_ord:Nnn { c } 1729 | \cs_generate_variant:Nn \__deriv_insert_var:Nnn { NV } 1730 | 1731 | \cs_generate_variant:Nn \__deriv_mixed_order:NNn { c } 1732 | \cs_generate_variant:Nn \__deriv_sort_method:Nn { c } 1733 | \cs_generate_variant:Nn \__deriv_eval_term:Nnnn { NVV } 1734 | \cs_generate_variant:Nn \__deriv_sort_lexical_auxi:nnn { VV } 1735 | 1736 | \cs_generate_variant:Nn \__deriv_set_default_auxi:Nnn { c } 1737 | \cs_generate_variant:Nn \__deriv_set_default_auxii:nnn { f } 1738 | \cs_generate_variant:Nn \__deriv_preamble_aux:nnn { V } 1739 | \cs_generate_variant:Nn \__deriv_var_bool_seq:NNN { c } 1740 | 1741 | \cs_generate_variant:Nn \deriv_binary_shift_left:Nn { NV } 1742 | \cs_generate_variant:Nn \__deriv_gcd_swap_helper:NNnn { NNff } 1743 | 1744 | \cs_generate_variant:Nn \__deriv_add_frac_to_seq:NNnnnnn { NNVVVV } 1745 | \cs_generate_variant:Nn \__deriv_add_to_seq:NNnn { NNVV, NNnV } 1746 | \cs_generate_variant:Nn \__deriv_update_seq:NNnn { NNVV, NNnV } 1747 | \cs_generate_variant:Nn \__deriv_update_seq:NNNNn { NNNNV } 1748 | \cs_generate_variant:Nn \__deriv_addfrac:NNnnnnn { NNVVxx } 1749 | 1750 | %%%%% Messages %%%%% 1751 | 1752 | \msg_new:nnnn { deriv } { command-already-defined } 1753 | { Command~'#1'~already~defined! } 1754 | { 1755 | You~have~used~#2~with~a~command~that~already~has~a~definition. \\ 1756 | The~existing~definition~of~'#1'~will~not~be~altered. 1757 | } 1758 | 1759 | \msg_new:nnnn { deriv } { derivative-not-defined } 1760 | { Derivative~'#1'~is~not~defined! } 1761 | { You~have~used~#2~with~a~derivative~that~was~never~defined. } 1762 | 1763 | \msg_new:nnnn { deriv } { command-not-defined } 1764 | { Command~'#1'~not~yet~defined! } 1765 | { You~have~used~#2~with~a~command~that~was~never~defined. } 1766 | 1767 | \msg_new:nnnn { deriv } { boolean-values-only } 1768 | { The~key~'#1'~accepts~boolean~values~only. } 1769 | { The~key~'#1'~only~accepts~the~values~'true'~and~'false'. } 1770 | 1771 | \msg_new:nnnn { deriv } { derivative-option-not-defined } 1772 | { Derivative~option~'#1'~not~yet~defined! } 1773 | { You~have~used~#2~with~a~derivative~option~that~was~never~defined. } 1774 | 1775 | \msg_new:nnnn { deriv } { differential-option-not-defined } 1776 | { Differential~option~'#1'~not~yet~defined! } 1777 | { You~have~used~#2~with~a~differential~option~that~was~never~defined. } 1778 | 1779 | \msg_new:nnnn { deriv } { differential-options-incompatible } 1780 | { Differential~options~#1~are~not~compatible! } 1781 | { You~have~used~#2~options~that~are~incompatible. } 1782 | 1783 | %%%%% Declaring derivatives %%%%% 1784 | 1785 | \@ifpackageloaded{mleftright} 1786 | { \derivset{all}[scale-auto = mleftmright] } 1787 | { \derivset{all}[scale-auto = leftright] } 1788 | 1789 | 1790 | \bool_if:NTF \l__deriv_pkg_italic_bool 1791 | { 1792 | \DeclareDerivative{\odv}{\mathnormal{d}} 1793 | \DeclareDerivative{\mdv}{\mathnormal{D}} 1794 | \DeclareDifferential{\odif}{\mathnormal{d}} 1795 | \DeclareDifferential{\mdif}{\mathnormal{D}}[style-var=mixed, style-var-*=multiple] 1796 | } 1797 | { 1798 | \DeclareDerivative{\odv}{\mathrm{d}} 1799 | \DeclareDerivative{\mdv}{\mathrm{D}} 1800 | \DeclareDifferential{\odif}{\mathrm{d}} 1801 | \DeclareDifferential{\mdif}{\mathrm{D}}[style-var=mixed, style-var-*=multiple] 1802 | } 1803 | 1804 | \DeclareDerivative{\fdv}{\delta} 1805 | \DeclareDerivative{\adv}{\Delta} 1806 | \DeclareDerivative{\jdv}{\partial}[fun=true, var=1] 1807 | \DeclareDerivative{\pdv}{\partial}[style-var=multiple, style-var-/=multiple, style-var-!=mixed, style-var-/!=multiple, delims-eval=(), delims-eval-/=(), delims-eval-!=()] 1808 | 1809 | \DeclareDifferential{\fdif}{\delta} 1810 | \DeclareDifferential{\adif}{\Delta} 1811 | \DeclareDifferential{\pdif}{\partial}[style-var=mixed, style-var-*=multiple] 1812 | 1813 | \endinput 1814 | 1815 | -------------------------------------------------------------------------------- /derivative.tex: -------------------------------------------------------------------------------- 1 | % derivative.tex 2 | % Copyright 2019-2024 Simon Jensen 3 | % 4 | % This work may be distributed and/or modified under the 5 | % conditions of the LaTeX Project Public License, either version 1.3 6 | % of this license or (at your option) any later version. 7 | % The latest version of this license is in 8 | % http://www.latex-project.org/lppl.txt 9 | % and version 1.3 or later is part of all distributions of LaTeX 10 | % version 2005/12/01 or later. 11 | % 12 | % This work has the LPPL maintenance status `maintained'. 13 | % 14 | % The Current Maintainer of this work is Simon Jensen. 15 | % Contributors: Romain Noel 16 | 17 | \begin{filecontents*}{macro.mst} 18 | headings_flag 1 19 | heading_prefix "\\begingroup \\ttfamily \\color\{RoyalBlue\}" 20 | heading_suffix "\\endgroup \\nopagebreak\n" 21 | item_0 "\n \\item \\begingroup \\small \\ttfamily \\upshape " 22 | delim_0 "\\endgroup, " 23 | group_skip "\n\n\\par\\bigskip\n" 24 | \end{filecontents*} 25 | 26 | \begin{filecontents*}{option.mst} 27 | item_0 "\n \\item \\begingroup \\color\{RoyalBlue\} " 28 | item_x1 "\\endgroup \n \\subitem \\begingroup \\small \\ttfamily \\upshape " 29 | item_1 "\n \\subitem \\begingroup \\small \\ttfamily \\upshape " 30 | delim_1 "\\endgroup, " 31 | group_skip "\n\n\\par\\bigskip\n" 32 | \end{filecontents*} 33 | 34 | \NeedsTeXFormat{LaTeX2e} 35 | 36 | \documentclass[final,british,10pt]{scrartcl} 37 | \reversemarginpar 38 | \RequirePackage[british]{babel} 39 | \RequirePackage{fontspec} 40 | %\RequirePackage{polyglossia} 41 | % \setmainlanguage[variant=british]{english} 42 | \RequirePackage[style=english,english=british]{csquotes} 43 | \RequirePackage[final,babel,auto]{microtype} 44 | \RequirePackage{xcolor} 45 | \definecolor{RoyalGray}{RGB}{127, 144, 158} 46 | \definecolor{RoyalDarkGray}{RGB}{78, 93, 104} 47 | \definecolor{RoyalLightGray}{RGB}{250, 250, 250} 48 | \definecolor{RoyalRed}{RGB}{157, 16, 45} 49 | \definecolor{RoyalBlue}{RGB}{0, 35, 102} 50 | \definecolor{RoyalGreen}{RGB}{32, 77, 2} 51 | 52 | % \definecolor{RoyalGray}{RGB}{75, 75, 75} 53 | % \definecolor{RoyalDarkGray}{RGB}{225, 225, 225} 54 | % \definecolor{RoyalLightGray}{RGB}{30, 30, 30} 55 | % \definecolor{RoyalRed}{RGB}{255, 177, 151} % 207, 102, 121 56 | % \definecolor{RoyalBlue}{RGB}{187, 134, 252} % 55, 185, 255 57 | % \definecolor{RoyalGreen}{RGB}{3, 218, 198} % 52, 177, 20 58 | % \definecolor{RoyalPageCoulor}{RGB}{18, 18, 18} % 30, 30, 30 59 | % \definecolor{RoyalTextCoulor}{RGB}{225, 225, 225} 60 | % \pagecolor{RoyalPageCoulor} 61 | % \color{RoyalTextCoulor} 62 | 63 | \RequirePackage{amsmath, amsthm} 64 | \allowdisplaybreaks 65 | \theoremstyle{remark} 66 | \newtheorem*{note}{Note} 67 | \RequirePackage{unicode-math} 68 | 69 | \RequirePackage{booktabs} 70 | \RequirePackage{tabularx} 71 | \RequirePackage{ragged2e} 72 | \RequirePackage{siunitx} 73 | \sisetup{locale = UK} 74 | \RequirePackage{hologo} 75 | \RequirePackage{enumitem} 76 | \RequirePackage{listings} 77 | \RequirePackage{imakeidx} 78 | \RequirePackage{calc} 79 | 80 | \RequirePackage{mleftright} 81 | \RequirePackage{xfrac} 82 | 83 | \RequirePackage[unicode]{hyperref} 84 | \RequirePackage[nameinlink]{cleveref} 85 | 86 | \makeatletter 87 | \ExplSyntaxOn 88 | 89 | \tl_new:N \pakkenavn 90 | \tl_new:N \titel 91 | \tl_new:N \email 92 | \tl_new:N \forfatter 93 | \tl_new:N \dato 94 | \tl_new:N \version 95 | 96 | \NewDocumentCommand{\Pakkenavn}{ m }{ \tl_gset:Nf \pakkenavn { \tl_trim_spaces:n { #1 } } } 97 | \NewDocumentCommand{\Titel} { m }{ \tl_gset:Nf \titel { \tl_trim_spaces:n { #1 } } } 98 | \NewDocumentCommand{\Forfatter}{ m }{ \tl_gset:Nf \forfatter { \tl_trim_spaces:n { #1 } } } 99 | \NewDocumentCommand{\Email} { m }{ \tl_gset:Nf \email { \tl_trim_spaces:n { #1 } } } 100 | \NewDocumentCommand{\Dato} { m }{ \tl_gset:Nf \dato { \tl_trim_spaces:n { #1 } } } 101 | \NewDocumentCommand{\Version} { m }{ \tl_gset:Nf \version { \tl_trim_spaces:n { #1 } } } 102 | 103 | \NewDocumentCommand{\mypackage}{ } { \pkg{\pakkenavn} } 104 | 105 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 106 | 107 | \NewDocumentCommand{\forside}{ m } 108 | { 109 | \thispagestyle{empty} 110 | 111 | \null\vspace{15mm}\noindent 112 | 113 | \begin{minipage}[t]{\textwidth} 114 | \centering 115 | \rule{\textwidth}{.4pt} \par \bigskip 116 | { \Huge \bfseries \tl_use:N \titel \par } \bigskip 117 | \rule{\textwidth}{.4pt} 118 | \end{minipage} \par \vspace{6mm} \noindent 119 | 120 | \begin{minipage}[t]{0.5\textwidth} 121 | \centering 122 | \textsl{Written~by:} \par 123 | { \color{RoyalRed} \forfatter \par } 124 | { \color{RoyalRed} \email \par } 125 | \end{minipage} 126 | \hfill 127 | \begin{minipage}[t]{0.5\textwidth} 128 | \centering 129 | \textsl{Released:} \par 130 | { \color{RoyalRed} v\version \par } 131 | { \color{RoyalRed} \dato \par } 132 | \end{minipage} 133 | 134 | \par \vspace{20mm} \noindent 135 | 136 | \begin{abstract} 137 | \noindent \ignorespaces 138 | #1 139 | \end{abstract} 140 | 141 | \vfill 142 | \clearpage 143 | } 144 | 145 | \lstdefinestyle{inlinestyle} 146 | { 147 | columns = fullflexible, 148 | basicstyle = \ttfamily\upshape\small, 149 | alsoletter = {\\,-,*,/,!}, 150 | keywords = [0]{style-inf, style-inf-num, style-inf-den, style-var, style-var-/, style-var-!, style-var-/!, style-frac, style-frac-/, style-notation, style-notation-*, scale-eval, scale-eval-/, scale-fun, scale-var, scale-var-!, scale-var-*, scale-frac, scale-frac-/, delims-eval, delims-eval-/, delims-fun, delims-var, delims-var-!, delims-var-*, delims-frac, delims-frac-/, sep-inf-ord, sep-inf-fun, sep-ord-fun, sep-frac-fun, sep-inf-var, sep-var-ord, sep-var-inf, sep-ord-inf, sep-ord-ord, sep-ord-var, sep-var-var, sep-eval-sb, sep-eval-sp, sep-begin, sep-end, switch-*, switch-/, switch-!, switch-sort, sort-method, sort-numerical, sort-abs-reverse, sort-lexical-reverse, sort-number-reverse, sort-sign-reverse, sort-symbol-reverse, fun, frac, var, order, ord, mixed-order, mixord, scale-auto}, 151 | keywordstyle = [0]\__mydoc_option_font:, 152 | keywords = [1]{\\odv, \\pdv, \\mdv, \\fdv, \\adv, \\jdv, \\odif, \\pdif, \\mdif, \\fdif, \\adif, \\NewDerivative, \\RenewDerivative, \\ProvideDerivative, \\DeclareDerivative, \\NewDifferential, \\RenewDifferential, \\ProvideDifferential, \\DeclareDifferential, \\slashfrac, \\derivset}, 153 | keywordstyle = [1]\__mydoc_function_font:, 154 | } 155 | 156 | \lstdefinestyle{definitionstyle} 157 | { 158 | style = inlinestyle, 159 | tabsize = 1, 160 | escapechar = \%, 161 | commentstyle = \footnotesize, 162 | frame = single, 163 | xleftmargin=3.4pt, 164 | xrightmargin=3.4pt, 165 | rulesep = 0pt, 166 | backgroundcolor = \color{RoyalLightGray}, 167 | rulecolor = \color{RoyalGray}, 168 | } 169 | 170 | \lstnewenvironment{definition}{\lstset{style=definitionstyle}\normalmarginpar}{\reversemarginpar} 171 | 172 | \newlist{todo}{enumerate}{1} 173 | \setlist[todo]{label=(\roman{todoi}), ref=\thesubsection(\roman{todoi})} 174 | \crefname{todoi}{todo}{todos} 175 | 176 | \newlist{changes}{enumerate}{1} 177 | \setlist[changes]{label=(\roman{changesi}), ref=\thesubsection(\roman{changesi})} 178 | \crefname{changesi}{change}{changes} 179 | 180 | \newlist{consideration}{enumerate}{1} 181 | \setlist[consideration]{label=(\roman{considerationi}), ref=\thesubsection(\roman{considerationi})} 182 | \crefname{considerationi}{consideration}{considerations} 183 | 184 | \AtEndPreamble 185 | { 186 | %\meaning\@idxitem\\ 187 | %\meaning\subitem\\ 188 | %\meaning\indexspace\\ 189 | %\meaning\hangindent 190 | %\meaning\indexspace 191 | \RenewDocumentCommand{\@idxitem}{}{\par \hangindent 0\p@ } 192 | \RenewDocumentCommand{\subitem}{}{\@idxitem \hspace *{0\p@ }} 193 | \RenewDocumentCommand{\indexspace}{}{\par \vskip 10\p@ \relax} 194 | } 195 | 196 | \NewDocumentCommand{\marginnote}{ m } 197 | { 198 | \leavevmode 199 | \marginline{\leavevmode \ttfamily\upshape\small \color{RoyalDarkGray} \tl_trim_spaces:n {#1} } 200 | } 201 | 202 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 203 | 204 | \NewDocumentCommand{\ket}{ m } 205 | { 206 | \lvert #1 \rangle 207 | } 208 | 209 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 210 | 211 | \NewDocumentCommand{\pkg}{ m } 212 | { 213 | \group_begin: 214 | \sffamily \upshape \small #1 215 | \group_end: 216 | } 217 | 218 | \NewDocumentCommand{\uni}{} % Kræver unicode 219 | { \textsuperscript{\texttt{U}} } 220 | 221 | \NewDocumentCommand{\pdf}{} % Kræver pdflatex 222 | { \textsuperscript{\texttt{P}} } 223 | 224 | \NewDocumentCommand{\req}{} % Kræver pakke 225 | { \textsuperscript{\texttt{R}} } 226 | 227 | \NewDocumentCommand{\tex}{}{\texorpdfstring{\hologo{TeX}}{TeX}} 228 | \NewDocumentCommand{\pdftex}{}{\texorpdfstring{\hologo{pdfTeX}}{pdfTeX}} 229 | \NewDocumentCommand{\luatex}{}{\texorpdfstring{\hologo{LuaTeX}}{LuaTeX}} 230 | \NewDocumentCommand{\xetex}{}{\texorpdfstring{\hologo{XeTeX}}{XeTeX}} 231 | \NewDocumentCommand{\latex}{ t2 t3 } 232 | { 233 | \bool_if:nTF {#1} 234 | { \texorpdfstring{\hologo{LaTeX2e}}{LaTeX2e} } 235 | { 236 | \bool_if:nTF {#2} 237 | { \texorpdfstring{\hologo{LaTeX3}}{LaTeX3} } 238 | { \LaTeX } 239 | } 240 | } 241 | 242 | \NewDocumentCommand{\xmark}{} 243 | { 244 | \textcolor{red}{\ensuremath{\mathord{\mathpalette\bigcdot@{}}}} 245 | } 246 | \NewDocumentCommand{\cmark}{} 247 | { 248 | \textcolor{green}{\ensuremath{\checkmark}} 249 | } 250 | 251 | \bool_new:N \l__mydoc_answer_bool 252 | \keys_define:nn {mydoc/answer} 253 | { 254 | done .bool_set:N = \l__mydoc_answer_bool, 255 | done .initial:n = false, 256 | done .default:n = true 257 | } 258 | 259 | \NewDocumentCommand{\answer}{ o m m } 260 | { 261 | \group_begin: 262 | \tl_if_novalue:nF {#1} { \mydoc_set_keys:nn {answer} {#1} } 263 | 264 | \bool_if:NTF \l__mydoc_answer_bool 265 | { 266 | \fcolorbox{RoyalGray}{RoyalLightGray} 267 | { 268 | \parbox{\dimexpr\linewidth-2\fboxsep\relax} 269 | { 270 | \__mydoc_answer:nn {#2} {#3} 271 | } 272 | } 273 | } 274 | { 275 | \__mydoc_answer:nn {#2} {#3} 276 | } 277 | \group_end: 278 | } 279 | 280 | \cs_new_protected:Npn \__mydoc_answer:nn #1 #2 281 | { 282 | #1 283 | \textbf{Conclusion:} 284 | \c_space_tl 285 | \group_begin: 286 | \slshape 287 | #2 288 | \group_end: 289 | } 290 | 291 | \newcommand*{\bigcdot@scalefactor}{1.25} 292 | \newcommand*{\bigcdot@widthfactor}{1.15} 293 | \newcommand*{\bigcdot@}[2]{ 294 | % #1: math style 295 | % #2: unused 296 | \sbox0{$#1\vcenter{}$}% math axis 297 | \sbox2{$#1\vectimes\m@th$} 298 | \hbox to \bigcdot@widthfactor\wd2{ 299 | \hfil 300 | \raise\ht0\hbox{ 301 | \scalebox{\bigcdot@scalefactor}{ 302 | \lower\ht0\hbox{$#1\vectimes\m@th$} 303 | } 304 | } 305 | \hfil 306 | } 307 | } 308 | 309 | 310 | 311 | \tl_new:N \l__mydoc_ch_version_tl 312 | \tl_new:N \l__mydoc_ch_date_tl 313 | \tl_new:N \l__mydoc_ch_change_tl 314 | 315 | \bool_new:N \l__mydoc_ch_beta_bool 316 | \bool_new:N \l__mydoc_ch_change_bool 317 | 318 | \keys_define:nn { mydoc/changelog } 319 | { 320 | version .tl_set:N = \l__mydoc_ch_version_tl, 321 | version .default:n = \c_novalue_tl, 322 | 323 | date .tl_set:N = \l__mydoc_ch_date_tl, 324 | date .default:n = \c_novalue_tl, 325 | 326 | beta .bool_set:N = \l__mydoc_ch_beta_bool, 327 | beta .default:n = {false} 328 | } 329 | 330 | \DeclareDocumentEnvironment{change}{ o } 331 | { 332 | \IfNoValueTF{#1} 333 | { \keys_set:nn { mydoc/changelog } { version, date, beta } } 334 | { \keys_set:nn { mydoc/changelog } { version, date, beta, #1 } } 335 | 336 | \mydoc_change_set: 337 | \mydoc_change_begin: 338 | } 339 | { 340 | \mydoc_change_end: 341 | } 342 | 343 | \cs_new_protected:Npn \mydoc_change_set: 344 | { 345 | \bool_set_true:N \l__mydoc_ch_change_bool 346 | \tl_set:Nn \l__mydoc_ch_change_tl 347 | { 348 | \leavevmode 349 | \marginline 350 | { 351 | \upshape \scriptsize \ttfamily 352 | %\leavevmode 353 | \null\vspace{-3.5\baselineskip}\null 354 | \tabular[t]{ r } 355 | \toprule 356 | v\tl_use:N \l__mydoc_ch_version_tl 357 | \\ 358 | \tl_use:N \l__mydoc_ch_date_tl 359 | \bool_if:NT \l__mydoc_ch_beta_bool 360 | { \\ \color{RoyalRed} Beta } 361 | \\ \bottomrule 362 | \endtabular 363 | } 364 | \ignorespaces 365 | } 366 | } 367 | 368 | \cs_new_protected:Npn \mydoc_change_begin: 369 | { 370 | \let\mydoc_item:\item 371 | 372 | \DeclareDocumentCommand{\item}{ o } 373 | { 374 | \tl_if_novalue:nTF {##1} 375 | { \mydoc_item: } 376 | { \mydoc_item: [##1] } 377 | \bool_if:NT \l__mydoc_ch_change_bool 378 | { 379 | \tl_use:N \l__mydoc_ch_change_tl 380 | \bool_set_false:N \l__mydoc_ch_change_bool 381 | } 382 | } 383 | \itemize[itemsep=0pt] 384 | } 385 | 386 | \cs_new_protected:Npn \mydoc_change_end: 387 | { 388 | \enditemize 389 | %\let\item\mydoc_item: 390 | } 391 | 392 | \NewDocumentEnvironment{changelog}{ } 393 | { 394 | \mydoc_ch_begin: 395 | } 396 | { 397 | \mydoc_ch_end: 398 | } 399 | 400 | \cs_new_protected:Npn \mydoc_ch_begin: 401 | { 402 | } 403 | 404 | \cs_new_protected:Npn \mydoc_ch_end: 405 | { 406 | } 407 | 408 | \ExplSyntaxOff 409 | 410 | 411 | \ExplSyntaxOn 412 | 413 | \tl_new:N \l__mydoc_number_tl 414 | \tl_new:N \l_mydoc_index_item_tl 415 | \tl_new:N \l_mydoc_index_subitem_tl 416 | \tl_new:N \l_mydoc_index_entry_tl 417 | 418 | \seq_new:N \l__mydoc_macro_arg_seq 419 | 420 | \seq_new:N \l__mydoc_group_seq 421 | \seq_new:N \l__mydoc_type_seq 422 | \seq_new:N \l__mydoc_function_seq 423 | \seq_new:N \g__mydoc_syntax_seq 424 | \seq_new:N \l__deriv_earg_seq 425 | 426 | \int_new:N \l__mydoc_earg_int 427 | \int_new:N \g__mydoc_function_int 428 | \int_new:N \g__mydoc_option_int 429 | 430 | \bool_new:N \l__mydoc_number_bool 431 | 432 | \tl_set:Nn \l__mydoc_number_tl {0123456789} 433 | 434 | \seq_new:N \l__mydoc_example_seq 435 | \int_new:N \g__mydoc_example_int 436 | 437 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 438 | 439 | \cs_new_protected:Npn \mydoc_define_vars_keys:nnnn #1 #2 #3 #4 440 | { 441 | \seq_set_from_clist:Nn \l__mydoc_group_seq {#4} 442 | \seq_map_inline:Nn \l__mydoc_group_seq 443 | { 444 | \mydoc_define_var:nnnn {#1} {#2} {#3} {##1} 445 | \mydoc_define_key:nnnn {#1} {#2} {#3} {##1} 446 | } 447 | } 448 | 449 | \cs_new_protected:Npn \mydoc_define_var:nnnn #1 #2 #3 #4 450 | { \use:c { #3_new:c } { #2__mydoc_#1_#4_#3 } } 451 | 452 | \cs_new_protected:Npn \mydoc_define_key:nnnn #1 #2 #3 #4 453 | { 454 | \str_if_eq:nnTF {#2} { g } 455 | { \keys_define:nn { mydoc/#1 } { #4 .#3_#2set:c = { #2__mydoc_#1_#4_#3 } } } 456 | { \keys_define:nn { mydoc/#1 } { #4 .#3_set:c = { #2__mydoc_#1_#4_#3 } } } 457 | } 458 | 459 | %\cs_new_protected:Npn \mydoc_define_inital:nnn #1 #2 #3 460 | %{ \keys_define:nn { mydoc/#1 } { #3 .initial:n = {#2} } } 461 | 462 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 463 | 464 | \cs_new_protected:Npn \mydoc_set_keys:nn #1 #2 465 | { 466 | \keys_set:nn { mydoc/#1 } {#2} 467 | } 468 | 469 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 470 | 471 | \cs_new_protected:Npn \mydoc_define_font_i:n #1 472 | { 473 | \mydoc_define_vars_keys:nnnn {#1} { l } { tl } { colour, family, shape, size } 474 | 475 | \cs_new_protected:cpn { __mydoc_#1_font: } 476 | { 477 | \color { \use:c { l__mydoc_#1_colour_tl } } 478 | \tl_use:c { l__mydoc_#1_family_tl } 479 | \tl_use:c { l__mydoc_#1_shape_tl } 480 | \tl_use:c { l__mydoc_#1_size_tl } 481 | } 482 | } 483 | 484 | \cs_new_protected:Npn \mydoc_define_font_ii:n #1 485 | { 486 | \mydoc_define_vars_keys:nnnn {#1} { l } { tl } { family, shape, size } 487 | \mydoc_define_vars_keys:nnnn {#1} { l } { bool } { familyb, shapeb, sizeb } 488 | 489 | \cs_new_protected:cpn { __mydoc_#1_font: } 490 | { 491 | \bool_if:cT { l__mydoc_#1_familyb_bool } { \tl_use:c { l__mydoc_#1_family_tl } } 492 | \bool_if:cT { l__mydoc_#1_shapeb_bool } { \tl_use:c { l__mydoc_#1_shape_tl } } 493 | \bool_if:cT { l__mydoc_#1_sizeb_bool } { \tl_use:c { l__mydoc_#1_size_tl } } 494 | } 495 | } 496 | 497 | \cs_new_protected:Npn \mydoc_define_index:n #1 498 | { 499 | \mydoc_define_vars_keys:nnnn {#1} { l } { bool } { index } 500 | \mydoc_define_vars_keys:nnnn {#1} { l } { bool } { definition } 501 | \mydoc_define_vars_keys:nnnn {#1} { l } { tl } { cat } 502 | } 503 | 504 | \cs_new_protected:Npn \mydoc_define_updated:n #1 505 | { 506 | \mydoc_define_vars_keys:nnnn {#1} { l } { tl } { new } 507 | \mydoc_define_vars_keys:nnnn {#1} { l } { tl } { updated } 508 | } 509 | 510 | \cs_new_protected:Npn \mydoc_define_default:n #1 511 | { 512 | \mydoc_define_vars_keys:nnnn {#1} { g } { clist } { default } 513 | \mydoc_define_vars_keys:nnnn {#1} { l } { tl } { sepa } 514 | \mydoc_define_vars_keys:nnnn {#1} { l } { tl } { sepb } 515 | \mydoc_define_vars_keys:nnnn {#1} { l } { tl } { sepc } 516 | } 517 | 518 | \cs_new_protected:Npn \mydoc_define_tabular:n #1 519 | { 520 | \mydoc_define_vars_keys:nnnn {#1} { l } { bool } { result } 521 | } 522 | 523 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 524 | 525 | \cs_new_protected:Npn \mydoc_define_type:nn #1 #2 526 | { 527 | \seq_set_from_clist:Nn \l__mydoc_type_seq {#2} 528 | \seq_map_inline:Nn \l__mydoc_type_seq 529 | { 530 | \str_case:nn {##1} 531 | { 532 | { font_i } { \mydoc_define_font_i:n {#1} } 533 | { font_ii } { \mydoc_define_font_ii:n {#1} } 534 | { index } { \mydoc_define_index:n {#1} } 535 | { default } { \mydoc_define_default:n {#1} } 536 | { tabular } { \mydoc_define_tabular:n {#1} } 537 | { updated } { \mydoc_define_updated:n {#1} } 538 | } 539 | } 540 | } 541 | 542 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 543 | 544 | \mydoc_define_type:nn { function } { font_i, index, updated } 545 | \mydoc_define_type:nn { macro } { font_ii, index } 546 | \mydoc_define_type:nn { syntax } { font_ii } 547 | \mydoc_define_type:nn { argument } { font_i, updated } 548 | \mydoc_define_type:nn { arg } { font_ii, } 549 | \mydoc_define_type:nn { option } { font_i, index, updated } 550 | \mydoc_define_type:nn { key } { font_ii, index } 551 | \mydoc_define_type:nn { values } { font_ii, default } 552 | \mydoc_define_type:nn { val } { font_ii } 553 | \mydoc_define_type:nn { example } { font_ii, tabular } 554 | \mydoc_define_type:nn { marg } { font_ii } 555 | \mydoc_define_type:nn { narg } { font_ii } 556 | \mydoc_define_type:nn { oarg } { font_ii } 557 | \mydoc_define_type:nn { targ } { font_ii } 558 | \mydoc_define_type:nn { meta } { font_ii } 559 | \mydoc_define_type:nn { cs } { font_ii } 560 | 561 | \mydoc_set_keys:nn { function } { family=\ttfamily, shape=\upshape, size=\small, colour=RoyalRed, index=true, definition=true, cat=\c_novalue_tl } 562 | \mydoc_set_keys:nn { macro } { family=\ttfamily, shape=\upshape, size=\small, familyb=true, shapeb=true, sizeb=true, index=true, definition=false, cat=\c_novalue_tl } 563 | \mydoc_set_keys:nn { syntax } { family=\rmfamily, shape=\upshape, size=\small, familyb=true, shapeb=true, sizeb=true } 564 | \mydoc_set_keys:nn { argument } { family=\rmfamily, shape=\upshape, size=\small, colour=RoyalBlue } 565 | \mydoc_set_keys:nn { arg } { family=\rmfamily, shape=\upshape, size=\small, familyb=true, shapeb=true, sizeb=true } 566 | \mydoc_set_keys:nn { option } { family=\ttfamily, shape=\upshape, size=\small, colour=RoyalGreen, index=true, definition=true, cat=\c_novalue_tl } 567 | \mydoc_set_keys:nn { key } { family=\ttfamily, shape=\upshape, size=\small, familyb=true, shapeb=true, sizeb=true, index=true, definition=false, cat=\c_novalue_tl } 568 | \mydoc_set_keys:nn { values } { family=\ttfamily, shape=\upshape, size=\small, familyb=true, shapeb=true, sizeb=true, default=\c_novalue_tl, sepa={ ,~}, sepb={ ,~}, sepc={ ,~} } 569 | \mydoc_set_keys:nn { val } { family=\ttfamily, shape=\upshape, size=\small, familyb=true, shapeb=true, sizeb=true } 570 | \mydoc_set_keys:nn { example } { family=\ttfamily, shape=\upshape, size=\small, familyb=true, shapeb=true, sizeb=true, result=true } 571 | \mydoc_set_keys:nn { marg } { family=\ttfamily, shape=\upshape, size=\small, familyb=true, shapeb=true, sizeb=true } 572 | \mydoc_set_keys:nn { narg } { family=\ttfamily, shape=\upshape, size=\small, familyb=true, shapeb=true, sizeb=true } 573 | \mydoc_set_keys:nn { oarg } { family=\ttfamily, shape=\upshape, size=\small, familyb=true, shapeb=true, sizeb=true } 574 | \mydoc_set_keys:nn { targ } { family=\ttfamily, shape=\upshape, size=\small, familyb=true, shapeb=true, sizeb=true } 575 | \mydoc_set_keys:nn { meta } { family=\rmfamily, shape=\slshape, size=\small, familyb=true, shapeb=true, sizeb=true } 576 | \mydoc_set_keys:nn { cs } { family=\rmfamily, shape=\upshape, size=\small, familyb=true, shapeb=true, sizeb=true } 577 | 578 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 579 | 580 | \prg_new_protected_conditional:Npnn \mydoc_if_int:n #1 { T, F, TF } 581 | { 582 | \tl_map_inline:Nn {#1} 583 | { 584 | \tl_if_in:NnTF \l__mydoc_number_tl {##1} 585 | { \bool_set_true:N \l__mydoc_number_bool } 586 | { \tl_map_break:n { \bool_set_false:N \l__mydoc_number_bool } } 587 | } 588 | \bool_if:NTF \l__mydoc_number_bool 589 | { \prg_return_true: } 590 | { \prg_return_false: } 591 | } 592 | 593 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 594 | 595 | \cs_new_protected:Npn \mydoc_vspace:n #1 596 | { 597 | \vspace{#1\baselineskip} 598 | } 599 | 600 | \cs_new_protected:Npn \mydoc_margin:n #1 601 | { 602 | \leavevmode 603 | \marginline 604 | { 605 | \leavevmode 606 | #1 607 | } 608 | \ignorespaces 609 | } 610 | 611 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 612 | 613 | \cs_new_protected:Npn \__mydoc_function_begin:n #1 614 | { 615 | \par 616 | \bool_if:NF {#1} { \mydoc_vspace:n { 0.3 } } 617 | \@afterindentfalse \@afterheading 618 | } 619 | 620 | \cs_new_protected:Npn \__mydoc_function_end: 621 | { 622 | \seq_gclear:N \g__mydoc_syntax_seq 623 | \par \noindent \ignorespacesafterend 624 | } 625 | 626 | \cs_new_protected:Npn \__mydoc_function_margin:n #1 627 | { 628 | \seq_set_from_clist:Nn \l__mydoc_function_seq {#1} 629 | \int_gzero:N \g__mydoc_function_int 630 | 631 | \mydoc_margin:n 632 | { 633 | \tabular[t]{ @{} r @{} } 634 | %\group_begin: 635 | \seq_map_inline:Nn \l__mydoc_function_seq 636 | { 637 | \__mydoc_function_font: 638 | \int_gincr:N \g__mydoc_function_int 639 | \mydoc_cs_to_str:N ##1 640 | \mydoc_index_cs:Nnn ##1 { function } { macro } 641 | \int_compare:nNnF { \g__mydoc_function_int } = { \seq_count:N \l__mydoc_function_seq } 642 | { \\ } 643 | } 644 | %\group_end: 645 | \deriv_new_updated:NN \l__mydoc_function_new_tl \l__mydoc_function_updated_tl 646 | \endtabular 647 | } 648 | } 649 | 650 | \cs_new_protected:Npn \deriv_new_updated:NN #1 #2 651 | { 652 | \tl_if_empty:NTF #1 653 | { 654 | \tl_if_empty:NF #2 655 | { 656 | \\ \midrule 657 | \deriv_add_updated:N #2 658 | } 659 | } 660 | { 661 | \\ \midrule 662 | \deriv_add_new:N #1 663 | \tl_if_empty:NF #2 664 | { 665 | \\ 666 | \deriv_add_updated:N #2 667 | } 668 | } 669 | } 670 | 671 | \cs_new_protected:Npn \deriv_add_new:N #1 672 | { 673 | \group_begin: 674 | \small \ttfamily 675 | New: \tl_use:N \c_space_tl 676 | 677 | \tl_if_head_eq_charcode:fNTF {#1} v 678 | { \tl_use:N #1 } 679 | { v\tl_use:N #1 } 680 | \group_end: 681 | } 682 | 683 | \cs_new_protected:Npn \deriv_add_updated:N #1 684 | { 685 | \group_begin: 686 | \small \ttfamily 687 | Updated: \tl_use:N \c_space_tl 688 | 689 | \tl_if_head_eq_charcode:fNTF {#1} v 690 | { \tl_use:N #1 } 691 | { v\tl_use:N #1 } 692 | \group_end: 693 | } 694 | 695 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 696 | 697 | \cs_new_protected:Npn \__mydoc_syntax_begin: 698 | { \ignorespaces } 699 | 700 | \cs_new_protected:Npn \mydoc_syntax:n #1 701 | { 702 | \seq_gset_from_clist:Nn \g__mydoc_syntax_seq {#1} 703 | 704 | \__mydoc_syntax_font: 705 | \seq_use:Nn \g__mydoc_syntax_seq { } 706 | } 707 | 708 | \cs_new_protected:Npn \__mydoc_syntax_end: 709 | { \par \mydoc_vspace:n { 0.2 } \noindent \ignorespacesafterend } 710 | 711 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 712 | 713 | \cs_new_protected:Npn \__mydoc_argument_begin:n #1 714 | { 715 | \par 716 | \bool_if:NF {#1} { \mydoc_vspace:n { 0.3 } } 717 | \@afterindentfalse \@afterheading 718 | } 719 | 720 | \cs_new_protected:Npn \__mydoc_argument_end: 721 | { 722 | \par\noindent\ignorespacesafterend 723 | } 724 | 725 | \cs_new_protected:Npn \__mydoc_argument_margin:n #1 726 | { 727 | \mydoc_margin:n 728 | { 729 | \tabular[t]{ @{} r @{} } 730 | \mydoc_set_keys:nn { marg } { familyb = false, shapeb = false, sizeb = false } 731 | \mydoc_set_keys:nn { narg } { familyb = false, shapeb = false, sizeb = false } 732 | \mydoc_set_keys:nn { oarg } { familyb = false, shapeb = false, sizeb = false } 733 | \mydoc_set_keys:nn { targ } { familyb = false, shapeb = false, sizeb = false } 734 | \mydoc_set_keys:nn { meta } { familyb = true, shapeb = true, sizeb = false } 735 | \mydoc_set_keys:nn { cs } { familyb = false, shapeb = false, sizeb = false } 736 | \__mydoc_argument_font: 737 | \mydoc_if_int:nTF {#1} 738 | { \seq_item:Nn \g__mydoc_syntax_seq {#1} } 739 | { #1 } 740 | \deriv_new_updated:NN \l__mydoc_argument_new_tl \l__mydoc_argument_updated_tl 741 | \endtabular 742 | } 743 | } 744 | 745 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 746 | 747 | \cs_new_protected:Npn \__mydoc_option_begin:n #1 748 | { 749 | \par 750 | \bool_if:NF {#1} { \mydoc_vspace:n { 0.3 } } 751 | \@afterindentfalse \@afterheading 752 | } 753 | 754 | \cs_new_protected:Npn \__mydoc_option_end: 755 | { 756 | \seq_clear:N \l__mydoc_option_seq 757 | \clist_gclear:c { g__mydoc_values_default_clist } 758 | \par \noindent \ignorespacesafterend 759 | } 760 | 761 | \cs_new_protected:Npn \__mydoc_option_margin:n #1 762 | { 763 | \seq_set_from_clist:Nn \l__mydoc_option_seq {#1} 764 | \int_gzero:N \g__mydoc_option_int 765 | 766 | \mydoc_margin:n 767 | { 768 | \tabular[t]{ @{} r @{} } 769 | \seq_map_inline:Nn \l__mydoc_option_seq 770 | { 771 | \int_gincr:N \g__mydoc_option_int 772 | \__mydoc_option_font: 773 | ##1 774 | \mydoc_index_key:nnn {##1} { option } { option } 775 | \int_compare:nNnF { \g__mydoc_option_int } = { \seq_count:N \l__mydoc_option_seq } 776 | { \\ } 777 | } 778 | \deriv_new_updated:NN \l__mydoc_option_new_tl \l__mydoc_option_updated_tl 779 | \endtabular 780 | } 781 | } 782 | 783 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 784 | 785 | \cs_new_protected:Npn \__mydoc_values_begin: 786 | { \ignorespaces } 787 | 788 | \cs_new_protected:Npn \mydoc_values:n #1 789 | { 790 | \seq_gset_from_clist:Nn \g__mydoc_values_seq {#1} 791 | 792 | \__mydoc_values_font: 793 | \seq_use:Nn \g__mydoc_values_seq { ,~} 794 | 795 | \exp_args:Nf \tl_if_novalue:nF { \clist_item:Nn \g__mydoc_values_default_clist { 1 } } 796 | { 797 | \hfill 798 | \mydoc_clist_use:n { values } 799 | } 800 | } 801 | 802 | \cs_new_protected:Npn \mydoc_clist_use:n #1 803 | { 804 | \clist_use:cnnn { g__mydoc_#1_default_clist } 805 | { \tl_use:c { l__mydoc_#1_sepa_tl } } 806 | { \tl_use:c { l__mydoc_#1_sepb_tl } } 807 | { \tl_use:c { l__mydoc_#1_sepc_tl } } 808 | } 809 | 810 | \cs_new_protected:Npn \__mydoc_values_end: 811 | { \par \mydoc_vspace:n { 0.2 } \noindent \ignorespacesafterend } 812 | 813 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 814 | 815 | \DeclareDocumentEnvironment{example}{ s o b } 816 | { 817 | \tl_if_novalue:nF {#2} { \mydoc_set_keys:nn { example } {#2} } 818 | \__mydoc_example_begin:nn {#1} {#3} 819 | } 820 | { 821 | \__mydoc_example_end: 822 | } 823 | 824 | \cs_new_protected:Npn \__mydoc_example_end: 825 | { 826 | \endtabular 827 | \endcenter 828 | } 829 | 830 | \cs_new_protected:Npn \__mydoc_example_begin:nn #1 #2 831 | { 832 | \seq_set_split:Nnn \l__deriv_example_seq { \\ } {#2} 833 | \bool_if:NTF \l__mydoc_example_result_bool 834 | { 835 | \bool_if:nTF {#1} 836 | { 837 | \center \tabular{ @{} c @{} } 838 | \__mydoc_example_content_star:N \l__deriv_example_seq 839 | } 840 | { 841 | \center \tabular{ @{} r c l @{} } 842 | \__mydoc_example_content:N \l__deriv_example_seq 843 | } 844 | } 845 | { 846 | \renewcommand{\arraystretch}{0} 847 | \center \tabular{ @{} >{\arraybackslash}l @{} } 848 | \__mydoc_example_content_nores:N \l__deriv_example_seq 849 | } 850 | } 851 | 852 | \cs_new_protected:Npn \__mydoc_example_content:N #1 853 | { 854 | \int_gzero:N \g__mydoc_example_int 855 | \seq_map_inline:Nn #1 856 | { 857 | \int_gincr:N \g__mydoc_example_int 858 | \__mydoc_example_font: 859 | \__mydoc_print:n {##1} 860 | & 861 | $\Longrightarrow$ 862 | & 863 | $\displaystyle ##1$ 864 | \int_compare:nNnF { \g__mydoc_example_int } = { \seq_count:N #1 } 865 | { \\ \addlinespace[0.5em] } 866 | } 867 | } 868 | 869 | \cs_new_protected:Npn \__mydoc_example_content_star:N #1 870 | { 871 | \int_gzero:N \g__mydoc_example_int 872 | \seq_map_inline:Nn #1 873 | { 874 | \int_gincr:N \g__mydoc_example_int 875 | \__mydoc_example_font: 876 | \__mydoc_print:n {##1} 877 | \\[0.5em] 878 | $\Longrightarrow \qquad \displaystyle ##1$ 879 | \int_compare:nNnF { \g__mydoc_example_int } = { \seq_count:N #1 } 880 | { \\ \addlinespace[0.5em] } 881 | } 882 | } 883 | 884 | \cs_new_protected:Npn \__mydoc_example_content_nores:N #1 885 | { 886 | \int_gzero:N \g__mydoc_example_int 887 | \seq_map_inline:Nn #1 888 | { 889 | \int_gincr:N \g__mydoc_example_int 890 | \__mydoc_example_font: 891 | \__mydoc_print:n {##1} 892 | \int_compare:nNnF { \g__mydoc_example_int } = { \seq_count:N #1 } 893 | { \\ \addlinespace[0.4em] } 894 | } 895 | } 896 | 897 | \tl_new:N \l__mydoc_print_tmp_tl 898 | \seq_new:N \l__deriv_print_seq 899 | \str_new:N \l__deriv_print_str 900 | 901 | \cs_new_protected:Npn \__mydoc_print:n #1 902 | { 903 | \tl_set:Nn \l__mydoc_print_tmp_tl {#1} 904 | \regex_replace_all:nnN { . } { \c{string} \0 } \l__mydoc_print_tmp_tl 905 | \str_set:Nx \l__deriv_print_str \l__mydoc_print_tmp_tl 906 | 907 | \__deriv_split_at_star:NN \l__deriv_print_seq \l__deriv_print_str 908 | } 909 | 910 | \cs_new_protected:Npn \__mydoc_inlinecode:n #1 911 | { 912 | \lstinline[style=inlinestyle]$#1$ 913 | } 914 | 915 | \cs_new_protected:Npn \__deriv_split_at_star:NN #1 #2 916 | { 917 | \seq_set_split:NnV \l_tmpa_seq {*} #2 918 | \bool_set_false:N \l__mydoc_star_bool 919 | \seq_clear:N \l__deriv_print_seq 920 | \seq_indexed_map_inline:Nn \l_tmpa_seq 921 | { 922 | \str_if_eq:eeTF { \tl_item:nn {##2} {-1} } { - } 923 | { 924 | \bool_set_true:N \l__mydoc_star_bool 925 | \__mydoc_inlinecode:n {##2*} 926 | } 927 | { 928 | \int_compare:nNnTF {##1} = { 1 } 929 | { \__mydoc_inlinecode:n {##2} } 930 | { 931 | \bool_if:NTF \l__mydoc_star_bool 932 | { 933 | \bool_set_false:N \l__mydoc_star_bool 934 | \__mydoc_inlinecode:n {##2} 935 | } 936 | { \hspace{0.7pt}\__mydoc_inlinecode:n {*##2} } 937 | } 938 | } 939 | } 940 | } 941 | 942 | %\bool_if:NTF \l__mydoc_star_bool 943 | %{ 944 | % \seq_put_right:Nn #1 {*##2} 945 | % \bool_set_false:N \l__mydoc_star_bool 946 | %} 947 | %{ \seq_put_right:Nn #1 {##2} } 948 | 949 | \NewDocumentCommand{\inlinecode}{ m } 950 | { 951 | \group_begin: 952 | \__mydoc_print:n {#1} 953 | \group_end: 954 | } 955 | 956 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 957 | 958 | \DeclareDocumentEnvironment{function}{ s m o } 959 | { 960 | \tl_if_novalue:nF {#3} { \mydoc_set_keys:nn { function } {#3} } 961 | \__mydoc_function_begin:n {#1} 962 | \__mydoc_function_margin:n {#2} 963 | } 964 | { 965 | \__mydoc_function_end: 966 | } 967 | 968 | \DeclareDocumentEnvironment{syntax}{ o b } 969 | { 970 | \tl_if_novalue:nF {#1} { \mydoc_set_keys:nn { syntax } {#1} } 971 | \__mydoc_syntax_begin: 972 | \mydoc_syntax:n {#2} 973 | } 974 | { 975 | \__mydoc_syntax_end: 976 | } 977 | 978 | \DeclareDocumentEnvironment{argument}{ s m o } 979 | { 980 | \tl_if_novalue:nF {#3} { \mydoc_set_keys:nn { argument } {#3} } 981 | \__mydoc_argument_begin:n {#1} 982 | \__mydoc_argument_margin:n {#2} 983 | } 984 | { 985 | \__mydoc_argument_end: 986 | } 987 | 988 | \DeclareDocumentEnvironment{option}{ s m o } 989 | { 990 | \tl_if_novalue:nF {#3} { \mydoc_set_keys:nn { option } {#3} } 991 | \__mydoc_option_begin:n {#1} 992 | \__mydoc_option_margin:n {#2} 993 | } 994 | { 995 | \__mydoc_option_end: 996 | } 997 | 998 | \DeclareDocumentEnvironment{values}{ o b } 999 | { 1000 | \tl_if_novalue:nF {#1} { \mydoc_set_keys:nn { values } {#1} } 1001 | \__mydoc_values_begin: 1002 | \mydoc_values:n {#2} 1003 | } 1004 | { 1005 | \__mydoc_values_end: 1006 | } 1007 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1008 | 1009 | \DeclareDocumentCommand{\default}{ s O{values} } 1010 | { 1011 | \group_begin: 1012 | \mydoc_default:nn {#1} {#2} 1013 | \group_end: 1014 | } 1015 | 1016 | \cs_new_protected:Npn \mydoc_default:nn #1 #2 1017 | { 1018 | \bool_if:nTF {#1} 1019 | { \clist_use:cnnn { g__mydoc_#2_default_clist } {~and~} { ,~} {~and~} } 1020 | { \clist_use:cn { g__mydoc_#2_default_clist } { ,~} } 1021 | } 1022 | 1023 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1024 | 1025 | \DeclareDocumentCommand{\macro}{ o m o } 1026 | { 1027 | \group_begin: 1028 | \tl_if_novalue:nF {#1} { \mydoc_set_keys:nn { macro } { #1 } } 1029 | \mydoc_macro:nn {#2} {#3} 1030 | \group_end: 1031 | } 1032 | 1033 | \cs_new_protected:Npn \mydoc_macro:nn #1 #2 1034 | { 1035 | \__mydoc_macro_font: 1036 | \mydoc_if_int:nTF {#1} 1037 | { 1038 | \tl_set:Nx \l__mydoc_marg_tl { \seq_item:Nn \l__mydoc_function_seq {#1} } 1039 | \mydoc_cs_to_str:x { \seq_item:Nn \l__mydoc_function_seq {#1} } 1040 | \exp_args:NV \mydoc_index_cs:Nnn \l__mydoc_marg_tl { macro } { macro } 1041 | } 1042 | { 1043 | \mydoc_cs_to_str:N #1 1044 | \mydoc_index_cs:Nnn #1 { macro } { macro } 1045 | } 1046 | \tl_if_novalue:nF {#2} 1047 | { 1048 | \seq_set_from_clist:Nn \l__mydoc_macro_arg_seq {#2} 1049 | \seq_map_function:NN \l__mydoc_macro_arg_seq \mydoc_arg:n 1050 | } 1051 | } 1052 | 1053 | \DeclareDocumentCommand{\arg}{ o m } 1054 | { 1055 | \group_begin: 1056 | \mydoc_arg:n {#2} 1057 | \group_end: 1058 | } 1059 | 1060 | \cs_new_protected:Npn \mydoc_arg:n #1 1061 | { 1062 | \__mydoc_arg_font: 1063 | \mydoc_if_int:nTF {#1} 1064 | { \seq_item:Nn \g__mydoc_syntax_seq {#1} } 1065 | { #1 } 1066 | } 1067 | 1068 | \DeclareDocumentCommand{\key}{ O{index=false} m } 1069 | { 1070 | \group_begin: 1071 | \tl_if_novalue:nF {#1} { \mydoc_set_keys:nn { key } {#1} } 1072 | \mydoc_key:n {#2} 1073 | \group_end: 1074 | } 1075 | 1076 | \AfterEndPreamble{ 1077 | \DeclareDocumentCommand{\val}{ s o m } 1078 | { 1079 | \group_begin: 1080 | \tl_if_novalue:nF {#2} { \mydoc_set_keys:nn { val } {#2} } 1081 | \bool_if:nTF {#1} 1082 | { \mydoc_val_star:n {#3} } 1083 | { \mydoc_val:n {#3} } 1084 | \group_end: 1085 | } 1086 | } 1087 | \DeclareDocumentCommand{\keyval}{ s o m m } 1088 | { 1089 | \group_begin: 1090 | \tl_if_novalue:nF {#2} { \mydoc_set_keys:nn { key } {#2} } 1091 | \bool_if:nTF {#1} 1092 | { \mydoc_keyval_star:nn {#3} {#4} } 1093 | { \mydoc_keyval:nn {#3} {#4} } 1094 | \group_end: 1095 | } 1096 | 1097 | \cs_new_protected:Npn \mydoc_key:n #1 1098 | { 1099 | \__mydoc_key_font: 1100 | #1 1101 | \mydoc_index_key:nnn {#1} { key } { option } 1102 | } 1103 | 1104 | \cs_new_protected:Npn \mydoc_val:n #1 1105 | { 1106 | \__mydoc_key_font: 1107 | #1 1108 | } 1109 | \cs_new_protected:Npn \mydoc_val_star:n #1 1110 | { 1111 | \__mydoc_key_font: 1112 | \{ #1 \} 1113 | } 1114 | 1115 | \cs_new_protected:Npn \mydoc_keyval:nn #1 #2 1116 | { 1117 | \group_begin: 1118 | \mydoc_key:n {#1} 1119 | = 1120 | \mydoc_val:n {#2} 1121 | \group_end: 1122 | } 1123 | \cs_new_protected:Npn \mydoc_keyval_star:nn #1 #2 1124 | { 1125 | \group_begin: 1126 | \mydoc_key:n {#1} 1127 | = 1128 | \mydoc_val_star:n {#2} 1129 | \group_end: 1130 | } 1131 | 1132 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1133 | 1134 | \cs_new_protected:Npn \mydoc_index_cs:Nnn #1 #2 #3 1135 | { 1136 | \tl_set:Nf \l_mydoc_index_item_tl { \cs_to_str:N #1 } 1137 | \tl_set:Nx \l_mydoc_index_entry_tl { \cstostr{#1} } 1138 | 1139 | \tl_set:Nf \l_mydoc_index_item_tl { \str_uppercase:f { \tl_head:N \l_mydoc_index_item_tl } } 1140 | 1141 | \bool_if:cT { l__mydoc_#2_index_bool } 1142 | { 1143 | \bool_if:cTF { l__mydoc_#2_definition_bool } 1144 | { \mydoc_index:VVnn \l_mydoc_index_item_tl \l_mydoc_index_entry_tl {#3} { textbf } } 1145 | { \mydoc_index:VVnn \l_mydoc_index_item_tl \l_mydoc_index_entry_tl {#3} { textnormal } } 1146 | } 1147 | } 1148 | 1149 | \cs_new_protected:Npn \mydoc_index_key:nnn #1 #2 #3 1150 | { 1151 | \seq_set_split:Nnn \l__mydoc_index_seq { - } {#1} 1152 | \mydoc_if_novalue:vTF { l__mydoc_#2_cat_tl } 1153 | { \tl_set:Nx \l_mydoc_index_item_tl { \seq_item:Nn \l__mydoc_index_seq {1} } } 1154 | { \tl_set_eq:Nc \l_mydoc_index_item_tl { l__mydoc_#2_cat_tl } } 1155 | 1156 | \tl_set:Nx \l_mydoc_index_subitem_tl {#1} 1157 | \tl_set:Nx \l_mydoc_index_entry_tl {#1} 1158 | 1159 | \tl_replace_all:Nnn \l_mydoc_index_subitem_tl { ! } { "! } 1160 | \tl_replace_all:Nnn \l_mydoc_index_entry_tl { ! } { "! } 1161 | 1162 | \bool_if:cT { l__mydoc_#2_index_bool } 1163 | { 1164 | \bool_if:cTF { l__mydoc_#2_definition_bool } 1165 | { \mydoc_index:VVVnn \l_mydoc_index_item_tl \l_mydoc_index_subitem_tl \l_mydoc_index_entry_tl {#3} { textbf } } 1166 | { \mydoc_index:VVVnn \l_mydoc_index_item_tl \l_mydoc_index_subitem_tl \l_mydoc_index_entry_tl {#3} { textnormal } } 1167 | } 1168 | } 1169 | \prg_new_conditional:Npnn \mydoc_if_novalue:n #1 { TF } 1170 | { 1171 | \token_if_macro:NTF {#1} 1172 | { 1173 | \exp_args:NV \tl_if_novalue:nTF {#1} 1174 | { \prg_return_true: } 1175 | { \prg_return_false: } 1176 | } 1177 | { 1178 | \tl_if_novalue:nTF {#1} 1179 | { \prg_return_true: } 1180 | { \prg_return_false: } 1181 | } 1182 | } 1183 | \prg_generate_conditional_variant:Nnn \mydoc_if_novalue:n { v } { TF } 1184 | 1185 | \cs_new_protected:Npn \mydoc_index:nnnn #1 #2 #3 #4 1186 | { 1187 | \index[#3]{#1@\protect{#2}|#4} 1188 | } 1189 | 1190 | \cs_new_protected:Npn \mydoc_index:nnnnn #1 #2 #3 #4 #5 1191 | { 1192 | \index[#4]{#1!#2@#3|#5} 1193 | } 1194 | \cs_generate_variant:Nn \mydoc_index:nnnnn { VVV } 1195 | \cs_generate_variant:Nn \mydoc_index:nnnn { VV } 1196 | 1197 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1198 | 1199 | \DeclareDocumentCommand{\tsb}{ m }{ \textsubscript{#1} } 1200 | 1201 | \DeclareDocumentCommand{\meta}{ m } 1202 | { 1203 | \ensuremath{\langle} 1204 | \group_begin: 1205 | \__mydoc_meta_font: 1206 | #1 1207 | \group_end: 1208 | \ensuremath{\rangle} 1209 | } 1210 | 1211 | \DeclareDocumentCommand{\marg}{ m } 1212 | { 1213 | \group_begin: 1214 | \mydoc_marg:n {#1} 1215 | \group_end: 1216 | } 1217 | \DeclareDocumentCommand{\narg}{ m } 1218 | { 1219 | \group_begin: 1220 | \mydoc_narg:n {#1} 1221 | \group_end: 1222 | } 1223 | \DeclareDocumentCommand{\oarg}{ s m } 1224 | { 1225 | \group_begin: 1226 | \bool_if:nTF {#1} 1227 | { \mydoc_oarg_star:n {#2} } 1228 | { \mydoc_oarg:n {#2} } 1229 | \group_end: 1230 | } 1231 | \DeclareDocumentCommand{\earg}{ m } 1232 | { 1233 | \group_begin: 1234 | \mydoc_earg:n {#1} 1235 | \group_end: 1236 | } 1237 | \DeclareDocumentCommand{\targ}{ m } 1238 | { 1239 | \group_begin: 1240 | \mydoc_targ:n {#1} 1241 | \group_end: 1242 | } 1243 | \DeclareDocumentCommand{\sarg}{ } 1244 | { 1245 | \group_begin: 1246 | \mydoc_sarg: 1247 | \group_end: 1248 | } 1249 | \DeclareDocumentCommand{\cs}{ m } 1250 | { 1251 | \group_begin: 1252 | \mydoc_cs:n {#1} 1253 | \group_end: 1254 | } 1255 | 1256 | \DeclareDocumentCommand{\csverb}{ v } 1257 | { 1258 | \group_begin: 1259 | \mydoc_csverb:n {#1} 1260 | \group_end: 1261 | } 1262 | 1263 | \cs_new:Npn \mydoc_marg:n #1 1264 | { 1265 | \__mydoc_marg_font: 1266 | \mydoc_arg_delim_format:n { \{ } 1267 | \meta{#1} 1268 | \mydoc_arg_delim_format:n { \} } 1269 | } 1270 | 1271 | \cs_new:Npn \mydoc_narg:n #1 1272 | { 1273 | \__mydoc_narg_font: 1274 | \mydoc_arg_delim_format:n { \{ } 1275 | #1 1276 | \mydoc_arg_delim_format:n { \} } 1277 | } 1278 | 1279 | \cs_new:Npn \mydoc_oarg:n #1 1280 | { 1281 | \__mydoc_oarg_font: 1282 | \mydoc_arg_delim_format:n { [ } 1283 | \meta{#1} 1284 | \mydoc_arg_delim_format:n { ] } 1285 | } 1286 | 1287 | \cs_new:Npn \mydoc_oarg_star:n #1 1288 | { 1289 | \__mydoc_oarg_font: 1290 | \mydoc_arg_delim_format:n { [ } 1291 | #1 1292 | \mydoc_arg_delim_format:n { ] } 1293 | } 1294 | 1295 | \cs_new:Npn \mydoc_earg:n #1 1296 | { 1297 | \seq_set_from_clist:Nn \l__deriv_earg_seq {#1} 1298 | 1299 | \int_zero:N \l__mydoc_earg_int 1300 | \seq_map_inline:Nn \l__deriv_earg_seq 1301 | { 1302 | \int_incr:N \l__mydoc_earg_int 1303 | \int_if_odd:nTF \l__mydoc_earg_int 1304 | { \mydoc_arg_delim_format:n {##1} } 1305 | { \mydoc_marg:n {##1} } 1306 | } 1307 | } 1308 | 1309 | \cs_new:Npn \mydoc_targ:n #1 1310 | { 1311 | \__mydoc_targ_font: 1312 | \mydoc_arg_delim_format:n {#1} 1313 | } 1314 | 1315 | \cs_new:Npn \mydoc_sarg: 1316 | { \mydoc_targ:n { * } } 1317 | 1318 | \cs_new:Npn \mydoc_cs:n #1 1319 | { 1320 | \__mydoc_cs_font: 1321 | \mydoc_arg_delim_format:n { \\#1 } 1322 | } 1323 | 1324 | \cs_new:Npn \mydoc_csverb:n #1 1325 | { 1326 | \__mydoc_cs_font: 1327 | \group_begin: 1328 | \ttfamily #1 1329 | \group_end: 1330 | } 1331 | 1332 | \cs_new:Npn \mydoc_arg_delim_format:n #1 1333 | { 1334 | \group_begin: 1335 | \ttfamily \char` #1 1336 | \group_end: 1337 | } 1338 | 1339 | \DeclareDocumentCommand{\low}{ O{0,0} m m } 1340 | { 1341 | \seq_set_from_clist:Nn \l__low_seq {#1} 1342 | 1343 | \mskip -\seq_item:Nn \l__low_seq {1} mu 1344 | \underbracket 1345 | { 1346 | \mskip \seq_item:Nn \l__low_seq {1} mu 1347 | \vphantom{f} 1348 | #2 1349 | \mskip \seq_item:Nn \l__low_seq {2} mu 1350 | } 1351 | \sb{\text{#3}} 1352 | \mskip -\seq_item:Nn \l__low_seq {2} mu 1353 | } 1354 | 1355 | \DeclareDocumentCommand{\ms}{ m } 1356 | { 1357 | {\scriptstyle\langle\texttt{#1}\rangle} 1358 | } 1359 | 1360 | \DeclareDocumentCommand{\here}{} 1361 | { 1362 | {\scriptstyle\langle\texttt{here}\rangle} 1363 | } 1364 | 1365 | \cs_new_protected:Npn \mydoc_cs_to_str:N #1 1366 | { \char` \\ \cs_to_str:N #1 } 1367 | 1368 | \cs_new_protected:Npn \mydoc_cs_to_str:n #1 1369 | { \char` \\ \cs_to_str:N #1 } 1370 | \cs_generate_variant:Nn \mydoc_cs_to_str:n { x } 1371 | 1372 | \DeclareDocumentCommand{\cstostr}{ m } 1373 | { \mydoc_cs_to_str:N #1 } 1374 | 1375 | \ExplSyntaxOff 1376 | \makeatother 1377 | 1378 | \Pakkenavn{derivative} 1379 | \Titel{The \pakkenavn{} package} 1380 | \Forfatter{Simon Jensen} 1381 | \Email{sjelatex@gmail.com} 1382 | \Dato{2024/02/08} 1383 | \Version{1.4} 1384 | 1385 | \RequirePackage{derivative}[\dato] 1386 | 1387 | \hypersetup 1388 | { 1389 | final = true, 1390 | bookmarksnumbered = true, 1391 | colorlinks = true, 1392 | linkcolor = RoyalRed, 1393 | urlcolor = RoyalBlue, 1394 | pdfauthor = \forfatter, 1395 | pdftitle = \titel, 1396 | pdfencoding = unicode 1397 | } 1398 | 1399 | \listfiles 1400 | 1401 | \setlength{\marginparwidth}{126pt} % 74.68849pt 1402 | \setlength{\marginparpush}{0pt} % 5.39996pt 1403 | 1404 | \makeindex[name=option, title=Index of Options, intoc=true] 1405 | \makeindex[name=macro, title=Index of Commands, intoc=true] 1406 | 1407 | \indexsetup{level=\subsection*, noclearpage=false, toclevel=subsection} 1408 | 1409 | \directlua{ 1410 | pdf.setmajorversion(2) 1411 | pdf.setminorversion(0) 1412 | } 1413 | 1414 | \begin{document} 1415 | 1416 | \forside{The \mypackage{} package provides a set of commands which makes writing ordinary and partial derivatives of arbitrary order in a straight forward manner. Additionally, this package provides a set of commands to define variants of the aforementioned derivatives. A set of optional arguments along with lots of package options allow for easy and great flexibility over the derivative's format, such as where the function is positioned, point of evaluation, and switching between fraction styles. Moreover, the mixed order of the partial derivative and variants hereof is automatically computed. This package is written in the \pkg{expl3} language and requires therefore the \LaTeX3 package bundles \pkg{l3kernel} and \pkg{l3package}. Additionally, the \pkg{mleftright} package is optional and provides the improved automatically scaling \cs{mleft} and \cs{mright}.} 1417 | 1418 | \clearpage 1419 | \tableofcontents 1420 | 1421 | \clearpage 1422 | \section{Introduction} 1423 | This package originated as a personal package I developed several years ago for various projects. Initially written in \tex{} and \latex{}, it encountered numerous errors as its complexity grew, eventually becoming a convoluted code. Consequently, I rewrote the code using the \latex3 language, allowing for easier maintenance. Originally, I created this package due to the lack of robust derivative packages available. However, I later discovered the \pkg{diffcoeff} package, which served the purpose well. Unfortunately, by that time, I had already written a most of the code, undocumented. To address this, I decided to document the code and transform it into a publicly available package. 1424 | 1425 | \bigskip 1426 | 1427 | Regarding terminology, I use the abbreviation \texttt{inf} to represent the operator symbols $d, \partial, \delta$, etc., commonly used in derivatives (e.g., $\odv{y}{x}, \pdv{y}{x}, \fdv{y}{x}$) and differentials (e.g., $\odif{x}, \pdif{x}, \fdif{x}$). In the description of macros and options, I often use the notation \emph{cs-\meta{placeholder}} to indicate a comma-separated list of \meta{placeholder}. For instance, \oarg{cs-numbers} is used in the option section to denote a comma-separated list of numbers for math space keys. It is important to note that whenever an argument specifies \meta{keyvalue list}, it refers to a comma-separated list of key-value pairs. 1428 | 1429 | \bigskip 1430 | 1431 | \noindent The GitHub repository for this package can be accessed at:\\ \href{https://github.com/sjelatex/derivative}{www.github.com/sjelatex/derivative}. 1432 | 1433 | 1434 | 1435 | \clearpage 1436 | \section{Derivative}\label{sec:derivative} 1437 | 1438 | \begin{function}*{\pdv}[updated=v1.3] 1439 | \begin{syntax} 1440 | \sarg, \oarg{keyval list}, \marg{function}, \targ{/}, \targ{!}, \marg{variables}, \earg{\_, point\tsb{1}, \^, point\tsb{2}} 1441 | \end{syntax} 1442 | The partial derivative is defined using the \macro{1} command, which has both mandatory and optional arguments. These arguments allow for the customization of specific parts and the style of the derivative. 1443 | \begin{definition} 1444 | \DeclareDerivative{\pdv}{\partial}[style-var=multiple, style-var-/=multiple, 1445 | style-var-!=mixed, style-var-/!=multiple, delims-eval=(), delims-eval-/=(), 1446 | delims-eval-!=()] 1447 | \end{definition} 1448 | 1449 | \begin{argument}*{1} 1450 | The optional first argument of \macro{1} controls the placement of the function in relation to the fraction. By setting \keyval{switch-*}{false}, the function is typeset in the numerator when the star is absent, and next to the fraction when the star is present. Here is an example: 1451 | \begin{example} 1452 | \pdv{f}{x,y} \\ 1453 | \pdv*{f}{x,y} 1454 | \end{example} 1455 | The behavior of the star can be reversed by setting \keyval{switch-*}{true}. In other words, the equations in the previous example will be interchanged. 1456 | \end{argument} 1457 | 1458 | \begin{argument}{2}[updated = v1.4] 1459 | The second argument of \macro{1}, enclosed in square brackets, is optional and used to specify options for the derivative using a \keyval[index=false]{key}{value} syntax. For instance, the order of differentiation can be set using the \key[cat=misc]{order} option. Here is an example: 1460 | \begin{example} 1461 | \pdv[order={2,3}]{f}{x,y,z} \\ 1462 | \pdv[order={\beta,a,n+2a}]{f}{x,y,z} \\ 1463 | \pdv[sep-var-inf=0]{f}{x,y,z} \\ 1464 | \pdv[order={3/2-n/3,n/2,1/3}]{f}{x,y,z} 1465 | \end{example} 1466 | To ease the cumbersome order key, implicit orders can now be given: 1467 | \begin{example} 1468 | \pdv[n+2, \alpha]{f}{x,y,z} 1469 | \end{example} 1470 | For a comprehensive list of available options that can be applied to derivatives, please refer to \cref{ssec:options_dv}. 1471 | %The order may be a number, a symbol and a combination hereof. Note that the total order of differentiation (i.e $\odif[order=n+2]{}$) is automatically calculated and sorted. This is particularly useful when dealing with mixed partial derivatives which is further described in \cref{ssec:DV_pdv,ssec:overall_order} 1472 | \end{argument} 1473 | 1474 | \begin{argument}{3} 1475 | The first mandatory argument of \macro{1} is used to typeset the function that will be differentiated. Here are some examples: 1476 | \begin{example} 1477 | \pdv{f(x,y,z)}{x,y,z} \\ 1478 | \pdv{e^x\sin(y)\ln(z)}{x,y,z} 1479 | \end{example} 1480 | The function is displayed either in the numerator or to the right of the derivative, depending on the presence or absence of the star argument. 1481 | \end{argument} 1482 | 1483 | \begin{argument}{4}[updated = v1.3] 1484 | The fourth argument of \macro{1} is an optional slash that appears between the function and the variable arguments, indicating an alternative style. Its behaviour depends on the presence or absence of the exclamation mark argument. 1485 | 1486 | When the exclamation mark is absent, the slash determines the fraction style in which the derivative is typeset. By default, when the slash is absent, the derivative is typeset with \cs{frac}, and when the slash is present, it is typeset with \cs{slashfrac}\footnote{Note that \cs{slashfrac} is a macro defined by the package, please refer to \cref{ssec:slashfrac} for more details.\label{foot:sfrac}}, as shown in the following example: 1487 | \begin{example} 1488 | \pdv{f}{x,y} \\ 1489 | \pdv{f}/{x,y} 1490 | \end{example} 1491 | However, when the exclamation mark argument is present, the slash argument switches between shorthand styles rather than fraction styles. 1492 | 1493 | Similar to the star argument, the effect of the slash's presence can be reversed by setting \keyval{switch-/}{true}. In other words, the equations in the previous example will be interchanged. 1494 | \end{argument} 1495 | 1496 | \begin{argument}{5}[new = v1.3] 1497 | The fifth argument of \macro{1} is an optional exclamation mark that appears between the function and the variable arguments. It allows switching the derivative into shorthand style, as described in \cref{ssec:options_dv}. 1498 | 1499 | When \keyval{switch-!}{false} is used, along with the \macro{1}'s default shorthand styles, the derivative is typeset as shown in the example below: 1500 | \begin{example} 1501 | \pdv{f}!{x,y} \\ 1502 | \pdv{f}/!{x,y} 1503 | \end{example} 1504 | The effect of the exclamation mark's presence can be reversed by setting \keyval{switch-!}{true}. In other words, the equations in the previous example will be interchanged. 1505 | \begin{note} 1506 | The order of the slash and exclamation mark is important. For example, \cs{pdv}\narg{f}\targ{!}\targ{/}\narg{x,y} will give $\pdv{f}!/{x,y}$ and not the indented output $\pdv{f}/!{x,y}$. 1507 | \end{note} 1508 | \end{argument} 1509 | 1510 | \begin{argument}{6} 1511 | This is the second and final mandatory argument is used to typeset the variable in which the function is differentiated with respect to. The variables should be provided as a comma-separated list 1512 | \begin{example} 1513 | \pdv{f}{x} \\ 1514 | \pdv{f}{x,y} 1515 | \end{example} 1516 | \end{argument} 1517 | 1518 | \clearpage 1519 | \begin{argument}{7} 1520 | The last optional argument specifies the point(s) of evaluation or variables held constant. It is an \emph{e-type} argument from the \pkg{xparse} package, denoted as \verb|e{_^}|. This means that the subscript \verb|_| and superscript \verb|^| accepts an argument given within braces. The order of the subscript and superscript is independent, as shown in the following examples: 1521 | \begin{example} 1522 | \pdv{f}{x,y}_{(x_1,y_1)} \\ 1523 | \pdv{f}{x,y}^{(x_2,y_2)} \\ 1524 | \pdv{f}{x,y}_{(x_1,y_1)}^{(x_2,y_2)} \\ 1525 | \pdv{f}{x,y}^{(x_2,y_2)}_{(x_1,y_1)} 1526 | \end{example} 1527 | The subscript argument is commonly used to indicate the point of evaluation or the variables held constant. If needed, the superscript argument can be used to denote a second point of evaluation. 1528 | \end{argument} 1529 | \end{function} 1530 | 1531 | \subsection{Other derivatives} 1532 | In addition to the partial derivative, the package also provides five other derivative commands: 1533 | \begin{itemize} 1534 | \item Ordinary derivative: \macro{\odv} - Used to represent the rate of change of a single-variable function with respect to its independent variable. 1535 | \item Material derivative: \macro{\mdv} - Applied in fluid mechanics and continuum mechanics to describe the rate of change of a quantity attached to a moving fluid particle. 1536 | \item Functional derivative: \macro{\fdv} - Used in functional analysis, calculus of variations, and quantum mechanics to express the derivative of a functional. 1537 | \item Average rate of change: \macro{\adv} - Used to denote the average rate of change of a quantity over a given interval. 1538 | \item Jacobian: \macro{\jdv} - Significant in multivariable calculus and linear algebra for representing the derivative of a vector-valued function. 1539 | \end{itemize} 1540 | A unique feature of this package is that it allows you to define your own derivatives, as described in \cref{ssec:defvar_dv}. This means you can create custom derivative commands tailored to your specific needs. 1541 | 1542 | If you require more information on the usage and customization of these derivative commands, please refer to the documentation in \cref{ssec:defvar_dv}. 1543 | 1544 | \clearpage 1545 | \begin{function}{\odv}[updated=v1.1] 1546 | \begin{syntax} 1547 | \sarg, \oarg{keyval list}, \marg{function}, \targ{/}, \marg{variables}, \earg{\_, point\tsb{1}, \^, point\tsb{2}} 1548 | \end{syntax} 1549 | In this package, the ordinary derivative is defined with an upright lowercase d if the package option \keyval[cat=misc]{upright}{true} is used. Otherwise, it is defined with an italic lowercase \textit{d}. This choice was made to align with the convention used in many modern books. 1550 | \begin{definition} 1551 | \DeclareDerivative{\odv}{\mathrm{d}}%\marginnote{\keyval[cat=misc]{upright}{true}}% 1552 | \DeclareDerivative{\odv}{\mathnormal{d}}%\marginnote{\keyval[cat=misc]{italic}{true}}% 1553 | \end{definition} 1554 | 1555 | \noindent The ordinary derivative can then be typeset as: 1556 | \begin{equation*} 1557 | \odv{f}{x} = \lim_{h\to 0} \mleft( \frac{ f(x+h) - f(x) }{ h } \mright) 1558 | \end{equation*} 1559 | By adjusting the \key{style-inf} or \key{style-inf-num} and \key{style-inf-den} keys, the operator d can be customized to personal preference or specific formatting requirements. 1560 | \end{function} 1561 | 1562 | \begin{function}{\mdv}[updated=v1.1] 1563 | \begin{syntax} 1564 | \sarg, \oarg{keyval list}, \marg{function}, \targ{/}, \marg{variables}, \earg{\_, point\tsb{1}, \^, point\tsb{2}} 1565 | \end{syntax} 1566 | The material derivative is defined with an upright uppercase D when the package option \keyval[cat=misc]{upright}{true}. Otherwise, it is defined with an italic uppercase D. 1567 | \begin{definition} 1568 | \DeclareDerivative{\mdv}{\mathrm{D}}%\marginnote{\keyval[cat=misc]{upright}{true}}% 1569 | \DeclareDerivative{\mdv}{\mathnormal{D}}%\marginnote{\keyval[cat=misc]{italic}{true}}% 1570 | \end{definition} 1571 | 1572 | \noindent In physics, the material derivative is defined by 1573 | \begin{equation*} 1574 | \mdv{ \varphi(\symbf{r}, t) }{ t } \coloneq \pdv{ \varphi(\symbf{r}, t) }{ t } + \dot{\symbf{r}} \cdot \nabla \varphi(\symbf{r}, t) 1575 | \end{equation*} 1576 | By adjusting the \key{style-inf} or \key{style-inf-num} and \key{style-inf-den} keys, the operator D can be customized to personal preference or specific formatting requirements. 1577 | \end{function} 1578 | 1579 | \begin{function}{\fdv} 1580 | \begin{syntax} 1581 | \sarg, \oarg{keyval list}, \marg{function}, \targ{/}, \marg{variables}, \earg{\_, point\tsb{1}, \^, point\tsb{2}} 1582 | \end{syntax} 1583 | In this package, the functional derivative is defined with a lowercase delta. By default, it is represented in italic form. The functional derivative can be defined as follows: 1584 | \begin{definition} 1585 | \DeclareDerivative{\fdv}{\delta} 1586 | \end{definition} 1587 | 1588 | \noindent In physics, the functional derivative is commonly employed in various equations, such as the Lagrange equation and the derivation of the Hartree-Fock equation. Examples of its usage include: 1589 | \begin{equation*} 1590 | \fdv{I}{q_{\alpha}} = \pdv{L}{q_{\alpha}} - \odv*{ \pdv{L}{ \dot{q}_{\alpha} } } { t } = 0, \qquad \fdv{ \symcal{L} }{ \psi_{n}^* } = \hat{F} \ket{\psi_{n}} - \epsilon_{n} \ket{\psi_{n}} = 0 1591 | , 1592 | \end{equation*} 1593 | \end{function} 1594 | 1595 | \begin{function}{\adv} 1596 | \begin{syntax} 1597 | \sarg, \oarg{keyval list}, \marg{function}, \targ{/}, \marg{variables}, \earg{\_, point\tsb{1}, \^, point\tsb{2}} 1598 | \end{syntax} 1599 | The average rate of change is defined to use an upright uppercase delta with the default settings. In this package, the average rate of change is defined as 1600 | \begin{definition} 1601 | \DeclareDerivative{\adv}{\Delta} 1602 | \end{definition} 1603 | 1604 | \noindent The average rate of change can be expressed as 1605 | \begin{equation*} 1606 | \adv{ y }{ x } = \frac{y_2- y_1}{x_2 - x_1} 1607 | \end{equation*} 1608 | \end{function} 1609 | 1610 | \begin{function}{\jdv}[updated = v1.0] 1611 | \begin{syntax} 1612 | \sarg, \oarg{keyval list}, \marg{function}, \targ{/}, \marg{variables}, \earg{\_, point\tsb{1}, \^, point\tsb{2}} 1613 | \end{syntax} 1614 | In this package, the Jacobian is defined with an italic partial differential by default. Additionally, a pair of parentheses is automatically inserted around the function and variable. 1615 | \begin{definition} 1616 | \DeclareDerivative{\jdv}{\partial}[fun=true, var=1] 1617 | \end{definition} 1618 | 1619 | \noindent which gives 1620 | \begin{equation*} 1621 | \jdv{f,g,h}{x,y,z} 1622 | \end{equation*} 1623 | \end{function} 1624 | 1625 | 1626 | 1627 | \clearpage 1628 | \section{Differentials}\label{sec:differential} 1629 | 1630 | \begin{function}*{\odif}[new = v1.0, updated=v1.1] 1631 | \begin{syntax} 1632 | \sarg, \oarg{keyval list}, \marg{variables} 1633 | \end{syntax} 1634 | The differential \macro{1} is defined with both mandatory and optional arguments that allow for customizing its typesetting and style. It is defined with an upright lowercase d when \keyval[cat=misc]{upright}{true} is used. Otherwise, it will be defined with an italic lowercase d. 1635 | \begin{definition} 1636 | \DeclareDifferential{\odif}{\mathrm{d}}%\marginnote{\keyval[cat=misc]{upright}{true}}% 1637 | \DeclareDifferential{\odif}{\mathnormal{d}}%\marginnote{\keyval[cat=misc]{italic}{true}}% 1638 | \end{definition} 1639 | 1640 | \begin{argument}*{1} 1641 | The first argument of \macro{1} is an optional star that determines the notation style of the differential. With the \keyval{switch-*}{false} option, the variables and orders are typeset as subscript and superscript, respectively, when the star is present. When the star is absent, the infinitesimal is placed in front of each variable, as illustrated below: 1642 | \begin{example} 1643 | \odif{x,y,z} \\ 1644 | \odif*{x,y,z} 1645 | \end{example} 1646 | The behavior of the star can be reversed by setting \keyval{switch-*}{true}. In other words, the equations in the previous example will be interchanged. 1647 | \end{argument} 1648 | 1649 | \begin{argument}{2}[updated = v1.4] 1650 | The second argument, enclosed in square brackets, is optional and is used to specify options for the differential using the \keyval[index=false]{key}{value} syntax. Here are some examples: 1651 | \begin{example} 1652 | \odif[order={n,3}]{x,y,z} \\ 1653 | \odif[sep-var-inf=0]{x,y,z} \\ 1654 | \odif*[sep-var-var=0]{x,y,z} 1655 | \end{example} 1656 | To ease the cumbersome order key, implicit orders can now be given: 1657 | \begin{example} 1658 | \odif[n+2, \alpha]{x,y,z} 1659 | \end{example} 1660 | For a comprehensive list of available options that can be applied to differentials, please refer to \cref{ssec:options_inf} 1661 | \end{argument} 1662 | 1663 | \begin{argument}{3} 1664 | The mandatory argument is used to typeset the variables in the differential. Here are some examples: 1665 | \begin{example} 1666 | \odif{x} \\ 1667 | \odif{s_1,s_2...,s_n} 1668 | \end{example} 1669 | \end{argument} 1670 | \end{function} 1671 | 1672 | \subsection{Other differentials} 1673 | In addition to the regular differential, the package also provides four other differential commands: 1674 | \begin{itemize} 1675 | \item Partial differential: \macro{\pdif} - This command is used to typeset partial differentials. 1676 | \item Uppercase D: \macro{\mdif} - It is used to typeset differentials with an uppercase "D". 1677 | \item Lowercase delta: \macro{\fdif} - This command is used to typeset differentials with a lowercase delta symbol. 1678 | \item Uppercase delta: \macro{\adif} - It is used to typeset differentials with an uppercase Delta symbol. 1679 | \end{itemize} 1680 | A unique feature of this package is that it allows you to define your own differentials, as described in \cref{ssec:defvar_inf}. This means you can create custom differential commands tailored to your specific needs. 1681 | 1682 | If you require more information on the usage and customization of these differential commands, please refer to the documentation in \cref{ssec:defvar_inf}. 1683 | 1684 | %This package offers four other differentials: partial differential \macro{\pdif}, uppercase D \macro{\mdif}, delta \macro{\fdif} and Delta \macro{\adif}. A unique feature of this package, is that you can define your own differential as described in \cref{ssec:defvar_inf}. 1685 | 1686 | \begin{function}{\pdif} 1687 | \begin{syntax} 1688 | \sarg, \oarg{keyval list}, \marg{variables} 1689 | \end{syntax} 1690 | The partial differential \macro{1} is commonly used as a shorthand notation for the partial derivative. In this package, it is defined as follows: 1691 | \begin{definition} 1692 | \DeclareDifferential{\pdif}{\partial}[style-notation=single, 1693 | style-notation-*=mixed] 1694 | \end{definition} 1695 | 1696 | \noindent The non-star and star versions are represented on the left side as: 1697 | \begin{align*} 1698 | \pdif[order={i,j,k}]{x,y,z} &\coloneq \pdv[order={i,j,k}]{}{x,y,z} \\ 1699 | \pdif*[order={i,j,k}]{x,y,z} &\coloneq \pdv[order={i,j,k}]{}{x,y,z} 1700 | \end{align*} 1701 | respectively. 1702 | \end{function} 1703 | 1704 | \begin{function}{\mdif}[updated=v1.1] 1705 | \begin{syntax} 1706 | \sarg, \oarg{keyval list}, \marg{variables} 1707 | \end{syntax} 1708 | Another commonly used shorthand notation for derivatives is the differential with an uppercase D. In this package it is defined with a upright D when \keyval[cat=misc]{upright}{true}. Otherwise, it is defined with an italic D. 1709 | \begin{definition} 1710 | \DeclareDifferential{\mdif}{\mathrm{D}}[style-notation=single, 1711 | style-notation-*=mixed]%\marginnote{\keyval[cat=misc]{upright}{true}}% 1712 | \DeclareDifferential{\mdif}{\mathnormal{D}}[style-notation=single, 1713 | style-notation-*=mixed%\marginnote{\keyval[cat=misc]{italic}{true}}% 1714 | \end{definition} 1715 | 1716 | \noindent The non-star and star version gives 1717 | \begin{align*} 1718 | \mdif[order={i,j,k}]{x,y,z} \\ 1719 | \mdif*[order={i,j,k}]{x,y,z} 1720 | \end{align*} 1721 | respectively. 1722 | \end{function} 1723 | 1724 | \begin{function}{\fdif} 1725 | \begin{syntax} 1726 | \sarg, \oarg{keyval list}, \marg{variables} 1727 | \end{syntax} 1728 | When working with functional derivatives, another commonly used differential is one that uses a delta symbol. It is defined as follows: 1729 | \begin{definition} 1730 | \DeclareDifferential{\fdif}{\delta} 1731 | \end{definition} 1732 | 1733 | \noindent For example, in expression like: 1734 | \begin{align*} 1735 | \fdif{J} = \int_{a}^{b} \pdv{L}{f} \fdif{f(x)} + \pdv{L}{f'} \odv*{ \fdif{f(x)} }{x} \odif{x} 1736 | \end{align*} 1737 | this differential is frequently encountered. 1738 | \end{function} 1739 | 1740 | \begin{function}{\adif} 1741 | \begin{syntax} 1742 | \sarg, \oarg{keyval list}, \marg{variables} 1743 | \end{syntax} 1744 | A differential for differences that uses a uppercase delta is defined as 1745 | \begin{definition} 1746 | \DeclareDifferential{\adif}{\Delta} 1747 | \end{definition} 1748 | 1749 | \noindent For example, the difference between two energy levels can be written as: 1750 | \begin{align*} 1751 | \adif{E} = E_2 - E_1 1752 | \end{align*} 1753 | \end{function} 1754 | 1755 | \clearpage 1756 | \section{Options} 1757 | This package accepts its options using the familiar \emph{key=value} syntax. The keys are divided into categories, with each key having its associated category as a prefix. 1758 | 1759 | \begin{function}{\derivset}[updated = v1.0] 1760 | \begin{syntax} 1761 | \marg{command}, \oarg{keyval list} 1762 | \end{syntax} 1763 | The \macro{1} command is used to set default values for derivative and differential options in the preamble. While it can be used within the document, the new \oarg{keyval list} arguments in the derivative and differential commands allow for more flexibility in specifying options on a per-use basis. 1764 | 1765 | \begin{argument}{1} 1766 | The mandatory argument determines which command the \emph{key=value} pairs are assigned to. The allowed \meta{commands} are the derivatives and differentials defined by the package, as well as any additional derivatives and differentials you have defined (see \cref{ssec:defvar_dv,ssec:defvar_inf} for more information). Additionally, the special value \texttt{all} is allowed, which provides access to the options that apply to all derivatives and differentials. 1767 | \begin{example} 1768 | \derivset{\odv}[switch-*=true] \odv{y}{x} \\ 1769 | \derivset{\odif}[switch-*=true] \odif{y}{x} 1770 | \end{example} 1771 | \end{argument} 1772 | 1773 | \begin{argument}{2} 1774 | The optional argument accepts input as a comma-separated list of \emph{key=value} pairs. If \arg{2} is omitted, the options will be set to the package's default settings for the chosen \arg{1}. For example, using the \macro{\derivset}[\narg{\macro{\odv}}] command will set the options for the ordinary derivative to the default settings defined by the package. 1775 | \begin{example} 1776 | \derivset{\odv}[switch-*=false] \odv{y}{x} \odv*{y}{x} \\ 1777 | \derivset{\odv}[switch-*=true] \odv{y}{x} \odv*{y}{x} \\ 1778 | \derivset{\odv} \odv{y}{x} \odv*{y}{x} 1779 | \end{example} 1780 | \end{argument} 1781 | \end{function} 1782 | 1783 | \subsection{Categories} 1784 | This section seeks to give a detailed description of each category. 1785 | 1786 | \begin{itemize} 1787 | \item The \key[index=false]{style-\meta{\dots}} keys allow you to customize the style of derivatives or differentials by specifying options such as the fraction command, infinitesimal notation (e.g., $d$, $\partial$) and its font, and variable treatment. 1788 | \item The \key[index=false]{delims-\meta{\dots}} keys sets the delimiters used around the \meta{\dots}. The Rule of Two applies: \enquote{Always two there are, no more, no less. A left and a right delimiter}. Only delimiters that can be scaled with commands like \cs{left}, \cs{big}, etc., are allowed. 1789 | \item The \key[index=false]{scale-\meta{\dots}} keys sets the size of the \meta{\dots}'s delimiters. The values \val{big}, \val{Big}, \val{bigg}, and \val{Bigg} are self-explanatory. The value \val{none} leaves the delimiters unscaled (except for periods, which are removed). The value \val{auto} automatically scales the delimiters using \cs{left} and \cs{right}. 1790 | \item The \key[index=false]{sep-\meta{\dots}-\meta{\dots}} keys inserts their value between \meta{\dots} and \meta{\dots}. If the value is a comma-separated list of up to three numbers (e.g. \texttt{\{1,2,3\}}) it is converted into the syntax \texttt{\cs{muskip} 1 mu plus 2 mu minus 3 mu} and used accordingly. For other values, they are used as given without any conversion. 1791 | \item The \key[index=false]{switch-\meta{\dots}} keys allow you to change the behaviour of an argument by swapping the effect of the presence or absence of an optional character argument. 1792 | \item The \key[index=false]{sort-\meta{\dots}} keys handle the sorting algorithm used for the mixed order. These keys allow you to choose the sorting method that best suits your preferences. 1793 | \item The miscellaneous keys do not fall into any of the previously mentioned categories and does not have a prefix. 1794 | \end{itemize} 1795 | 1796 | \begin{note} 1797 | A value with a superscripted \texttt{R} indicates that it requires a specific package to be loaded. Additionally, some keys have multiple versions, denoted by \texttt{-/}, \texttt{-!}, and \texttt{-/!} at the end. These keys are specifically related to the slash and exclamation mark arguments. 1798 | \end{note} 1799 | 1800 | \subsection{Package options} 1801 | The package options can be used with the following syntax when loading the package in the preamble: 1802 | \begin{center} 1803 | \ttfamily\small 1804 | \cs{usepackage}\oarg{keyval list}\narg{derivative} 1805 | \end{center} 1806 | 1807 | \begin{option}*{italic}[cat=misc, new = v1.1] 1808 | \begin{values}[default = false] 1809 | true, false 1810 | \end{values} 1811 | Sets the font style of the infinitesimals $d$ and $D$ used in \cs{odv}, \cs{mdv}, \cs{odif} and \cs{mdif} to italic using \cs{mathnormal}. The \key[cat=misc,index=false]{italic} and \key[cat=misc,index=false]{upright} options are mutually exclusive. 1812 | \end{option} 1813 | 1814 | \begin{option}{upright}[cat=misc, new = v1.1] 1815 | \begin{values}[default = true] 1816 | true, false 1817 | \end{values} 1818 | Sets the font style of the infinitesimals $d$ and $D$ used in \cs{odv}, \cs{mdv}, \cs{odif} and \cs{mdif} to upright using \cs{mathrm}. The \key[cat=misc,index=false]{italic} and \key[cat=misc,index=false]{upright} options are mutually exclusive. 1819 | \end{option} 1820 | 1821 | \subsection{Derivative options} \label{ssec:options_dv} 1822 | The options in this subsection are available fo customizing the behaviour of derivatives defined by the package and you.% using the commands described in \cref{ssec:defvar_dv}. 1823 | 1824 | \subsubsection*{Style} 1825 | 1826 | \begin{option}*{style-inf}[updated = {v1.0, v1.3}] 1827 | \begin{values}[default = ] 1828 | \meta{math-font-style}\meta{infinitesimal} 1829 | \end{values} 1830 | Sets the infinitesimal used in the derivative. This is a meta key, which means it sets the value of both \key{style-inf-num} and \key{style-inf-den} at the same time. 1831 | \begin{example} 1832 | \odv[style-inf=\symbf{d}]{f}{x} 1833 | \end{example} 1834 | \end{option} 1835 | 1836 | \begin{option}{style-inf-num}[new = v1.3] 1837 | \begin{values}[default = d] 1838 | \meta{math-font-style}\meta{infinitesimal} 1839 | \end{values} 1840 | Sets the infinitesimal used in the numerator of the derivative. This option is also used in the shorthand versions, i.e., when the exclamation mark argument is used. The default infinitesimal is a plain \default. 1841 | \begin{example} 1842 | \odv[style-inf-num=\mathbf{d}]{f}{x} \\ 1843 | \odv[style-inf-num=\mathbf{d}]{f}!{x} 1844 | \end{example} 1845 | \end{option} 1846 | 1847 | \begin{option}{style-inf-den}[new = v1.3] 1848 | \begin{values}[default = d] 1849 | \meta{math-font-style}\meta{infinitesimal} 1850 | \end{values} 1851 | Sets the infinitesimal used in the denominator of the derivative. The default infinitesimal is a plain \default. 1852 | \begin{example} 1853 | \odv[style-inf-den=\mathbf{d}]{f}{x} 1854 | \end{example} 1855 | \end{option} 1856 | 1857 | \begin{option}{style-frac} 1858 | \begin{values}[default = \cs{frac}] 1859 | \meta{fraction} 1860 | \end{values} 1861 | The derivative uses the fraction set by this key when the slash argument is absent. If \keyval{switch-/}{true}, the derivative uses this fraction when the slash argument is present. The key's default value is the usual fraction \cs{frac}. 1862 | \begin{example} 1863 | \odv[style-frac=\tfrac]{f}{x} \\ 1864 | \odv[switch-/=true, style-frac=\tfrac]{f}/{x} 1865 | \end{example} 1866 | \end{option} 1867 | 1868 | \begin{option}{style-frac-/} 1869 | \begin{values}[default = \cs{slashfrac}] 1870 | \meta{fraction} 1871 | \end{values} 1872 | The derivative uses the fraction set by this key when the slash argument is present. If \keyval{switch-/}{true}, the derivative uses this fraction when the slash argument is absent. The key's default value is a text-styled fraction \val{\default}\footref{foot:sfrac} on the form $\odv[style-frac-/=\slashfrac, switch-/=false]{f}/{x}$. 1873 | \begin{example} 1874 | \odv[style-frac-/=\sfrac]{f}/{x} 1875 | \end{example} 1876 | \end{option} 1877 | 1878 | \begin{option}{style-var}[new = v1.0] 1879 | \begin{values}[default = single] 1880 | single, multiple 1881 | \end{values} 1882 | This option determines how the derivative treats its variables and orders when both the slash argument and the exclamation mark are absent assuming \keyval{switch-/}{false} and \keyval{switch-!}{false} 1883 | \begin{itemize}[widest = {\val{multiple}}, leftmargin =*] 1884 | \item[\val{single}] The derivative behaves like a ordinary derivative, treating the variable argument and order as single entities. 1885 | \item[\val{multiple}] The derivative behaves like a partial derivative, treating the variable argument as a list of comma-separated variables. The mixed order is automatically calculated and sorted based on the \keyval[cat=misc]{order}{\meta{cs-orders}} key. See \cref{ssec:overall_order} for limitations on the automatic calculation. 1886 | \end{itemize} 1887 | %This option determines how the derivative treats its variables. The variable argument is treated as a single variable and the order is treated as a single order when \val{single} is used. The variable argument is treated as a comma separated list of variables with \val{multiple} similarly to a partial derivative. Moreover the mixed order is automatically calculated from the list of orders given in \keyval[cat=misc]{order}{\meta{order}}. 1888 | \begin{example} 1889 | \pdv[style-var=single, order={1,2,3}]{f}{x,y,z} \\ 1890 | \pdv[style-var=multiple]{f}{x,y,z} 1891 | \end{example} 1892 | \end{option} 1893 | 1894 | \begin{option}{style-var-/}[new = v1.3] 1895 | \begin{values}[default = single] 1896 | single, multiple 1897 | \end{values} 1898 | This option behaves identically to \key{style-var}, however it is used when the slash argument is present and the exclamation mark is absent assuming \keyval{switch-/}{false} and \keyval{switch-!}{false}. 1899 | \begin{example} 1900 | \pdv[style-var-/=single, order={1,2,3}]{f}/{x,y,z} \\ 1901 | \pdv[style-var-/=multiple]{f}/{x,y,z} 1902 | \end{example} 1903 | \end{option} 1904 | 1905 | \begin{option}{style-var-!}[new = v1.3] 1906 | \begin{values}[default = multiple] 1907 | single, multiple, mixed 1908 | \end{values} 1909 | This options determines the shorthand notation of the derivative when the slash argument is absent and the exclamation mark is present assuming \keyval{switch-/}{false} and \keyval{switch-!}{false}. 1910 | \begin{itemize}[widest = {\val{multiple}}, leftmargin =*] 1911 | \item[\val{single}] Creates a single differential with variables as subscripts and orders as superscripts. 1912 | \item[\val{multiple}] Creates a separate differential for each variable. 1913 | \item[\val{mixed}] Creates a separate differential for each variable but with variables as subscripts and orders as superscripts. 1914 | \end{itemize} 1915 | %When \val{single} is used, a single differential is created with the variables and orders in a subscript and superscript, respectively. The value \val{multiple} creates a differential for each variable. While the value \val{mixed} creates differentials their variable and order in a subscript and superscript, respectively. 1916 | \begin{example} 1917 | \pdv[style-var-!=single]{f}!{x,y,z} \\ 1918 | \pdv[style-var-!=multiple]{f}!{x,y,z} \\ 1919 | \pdv[style-var-!=mixed]{f}!{x,y,z} 1920 | \end{example} 1921 | \end{option} 1922 | 1923 | \begin{option}{style-var-/!}[new = v1.3] 1924 | \begin{values}[default = single] 1925 | single, multiple, mixed 1926 | \end{values} 1927 | This option behaves identical to \key{style-var-!}, however it is used when both the exclamation mark and slash arguments are present assuming \keyval{switch-/}{false} and \keyval{switch-!}{false}. 1928 | \begin{example} 1929 | \pdv[style-var-/!=single]{f}/!{x,y,z} \\ 1930 | \pdv[style-var-/!=multiple]{f}/!{x,y,z} \\ 1931 | \pdv[style-var-/!=mixed]{f}/!{x,y,z} 1932 | \end{example} 1933 | \end{option} 1934 | 1935 | \subsubsection*{Scaling} 1936 | 1937 | \begin{option}*{scale-eval} 1938 | \begin{values}[default = auto] 1939 | auto, none, big, Big, bigg, Bigg 1940 | \end{values} 1941 | Sets the size of the delimiters used for the point of evaluation. It is applied when the slash argument is absent, assuming \keyval{switch-/}{false}. The default behaviour is to automatically scale the delimiters. 1942 | \begin{example} 1943 | \pdv[scale-eval=auto]{f}{x,y}_{(x_0,y_0)}\\ 1944 | \pdv[scale-eval=auto]{f}!{x,y}_{(x_0,y_0)} 1945 | \end{example} 1946 | \end{option} 1947 | 1948 | \begin{option}{scale-eval-/} 1949 | \begin{values}[default = auto] 1950 | auto, none, big, Big, bigg, Bigg 1951 | \end{values} 1952 | Sets the size of the delimiters used for the point of evaluation. It is applied when the slash argument is present, assuming \keyval{switch-/}{false}. The default behaviour is to automatically scale the delimiters. 1953 | \begin{example} 1954 | \pdv[scale-eval-/=none]{f}/{x,y}_{(x_0,y_0)} 1955 | \end{example} 1956 | \end{option} 1957 | 1958 | \begin{option}{scale-eval-!}[new = v1.3] 1959 | \begin{values}[default = auto] 1960 | auto, none, big, Big, bigg, Bigg 1961 | \end{values} 1962 | Sets the size of the delimiters used for the point of evaluation. It is applied when the exclamation mark argument is present, assuming \keyval{switch-!}{false}. The default behaviour is to automatically scale the delimiters. This option takes priority over \key{scale-eval-/} when the slash argument is also present. 1963 | \begin{example} 1964 | \pdv[scale-eval-!=Big]{f}!{x,y}_{(x_0,y_0)} 1965 | \end{example} 1966 | \end{option} 1967 | 1968 | \begin{option}{scale-fun} 1969 | \begin{values}[default = auto] 1970 | auto, none, big, Big, bigg, Bigg 1971 | \end{values} 1972 | Sets the size of the delimiters used around the function. It is applied when \keyval[cat=misc]{fun}{true}. The default behaviour is to automatically scale the delimiters. 1973 | \begin{example} 1974 | \pdv[scale-fun=big, fun]{f}{x,y} 1975 | \end{example} 1976 | \end{option} 1977 | 1978 | \begin{option}{scale-var} 1979 | \begin{values}[default = auto] 1980 | auto, none, big, Big, bigg, Bigg 1981 | \end{values} 1982 | Sets the size of the delimiters used around the variables specified by the \keyval*[cat=misc,index=false]{var}{\dots} option when the exclamation mark argument is absent assuming \keyval{switch-!}{false}. The default behaviour is to automatically scale the delimiters. 1983 | \begin{example} 1984 | \pdv[scale-var=Big, var]{f}{x,y} 1985 | \end{example} 1986 | \end{option} 1987 | 1988 | \begin{option}{scale-var-!}[new = v1.3] 1989 | \begin{values}[default = auto] 1990 | auto, none, big, Big, bigg, Bigg 1991 | \end{values} 1992 | Sets the size of the delimiters used around the variables specified by the \keyval*[cat=misc,index=false]{var}{\dots} option when the exclamation mark argument is present assuming \keyval{switch-!}{false}. The default behaviour is to automatically scale the delimiters. 1993 | \begin{example} 1994 | \pdv[scale-var-!=big, var]{f}!{x,y} 1995 | \end{example} 1996 | \end{option} 1997 | 1998 | \begin{option}{scale-frac} 1999 | \begin{values}[default = auto] 2000 | auto, none, big, Big, bigg, Bigg 2001 | \end{values} 2002 | Sets the size of the delimiters used for around the fraction. It is applied when the slash argument is absent and \keyval[cat=misc]{frac}{true}, assuming \keyval{switch-/}{false}. The default behaviour is to automatically scale the delimiters. 2003 | \begin{example} 2004 | \pdv[scale-frac=bigg, frac]{f}{x,y} 2005 | \end{example} 2006 | \end{option} 2007 | 2008 | \begin{option}{scale-frac-/} 2009 | \begin{values}[default = auto] 2010 | auto, none, big, Big, bigg, Bigg 2011 | \end{values} 2012 | Sets the size of the delimiters used for around the fraction. It is applied when the slash argument is present and \keyval[cat=misc]{frac}{true}, assuming \keyval{switch-/}{false}. The default behaviour is to automatically scale the delimiters. 2013 | \begin{example} 2014 | \pdv[scale-frac-/=Bigg, frac]{f}/{x,y} 2015 | \end{example} 2016 | \end{option} 2017 | 2018 | \subsubsection*{Delimiters} 2019 | 2020 | \begin{option}*{delims-eval} 2021 | \begin{values}[default = .~\cs{rvert}] 2022 | \meta{left delimiter}\meta{right delimiter} 2023 | \end{values} 2024 | Sets the delimiters used to indicate the point of evaluation. These delimiters are used when the slash argument is absent, assuming \keyval{switch-/}{false}. The key's default delimiters are a period and a vertical line. 2025 | \begin{example} 2026 | \pdv[delims-eval=.|]{f}{x,y}_{(x_0,y_0)} 2027 | \end{example} 2028 | \end{option} 2029 | 2030 | \begin{option}{delims-eval-/} 2031 | \begin{values}[default = .~\cs{rvert}] 2032 | \meta{left delimiter}\meta{right delimiter} 2033 | \end{values} 2034 | Sets the delimiters used to indicate the point of evaluation. These delimiters are used when the slash argument is present, assuming \keyval{switch-/}{false}. The key's default delimiters are a period and a vertical line. 2035 | \begin{example} 2036 | \pdv[delims-eval-/=[]]{f}/{x,y}_{(x_0,y_0)} 2037 | \end{example} 2038 | \end{option} 2039 | 2040 | \begin{option}{delims-eval-!}[new = v1.3] 2041 | \begin{values}[default = .~\cs{rvert}] 2042 | \meta{left delimiter}\meta{right delimiter} 2043 | \end{values} 2044 | Sets the delimiters used to indicate the point of evaluation. These delimiters are used when the slash argument is present, assuming \keyval{switch-!}{false}. The key's default delimiters are a period and a vertical line. This option takes priority over \key{delims-eval-/} when the slash argument is also present. 2045 | \begin{example} 2046 | \pdv[delims-eval-!=[]]{f}!{x,y}_{(x_0,y_0)} 2047 | \end{example} 2048 | \end{option} 2049 | 2050 | \begin{option}{delims-fun} 2051 | \begin{values}[default = (~)] 2052 | \meta{left delimiter}\meta{right delimiter} 2053 | \end{values} 2054 | Sets the delimiters used around the function. These delimiters are used when \keyval[cat=misc]{fun}{true}. The key's default delimiters are parentheses. 2055 | \begin{example} 2056 | \pdv[delims-fun=\langle\rangle, fun]{f}{x,y} 2057 | \end{example} 2058 | \end{option} 2059 | 2060 | \begin{option}{delims-var} 2061 | \begin{values}[default = (~)] 2062 | \meta{left delimiter}\meta{right delimiter} 2063 | \end{values} 2064 | Sets the delimiters used around the variables specified by the \keyval*[cat=misc,index=false]{var}{\dots} option when the exclamation mark argument is absent assuming \keyval{switch-!}{false}. The key's default delimiters are parentheses. 2065 | \begin{example} 2066 | \pdv[delims-var=\{\}, var]{f}{x,y} 2067 | \end{example} 2068 | \end{option} 2069 | 2070 | \begin{option}{delims-var-!}[new = v1.3] 2071 | \begin{values}[default = (~)] 2072 | \meta{left delimiter}\meta{right delimiter} 2073 | \end{values} 2074 | Sets the delimiters used around the variables specified by the \keyval*[cat=misc,index=false]{var}{\dots} option when the exclamation mark argument is present assuming \keyval{switch-!}{false}. The key's default delimiters are parentheses. 2075 | \begin{example} 2076 | \pdv[delims-var-!=\lceil\rceil, var]{f}!{x,y} 2077 | \end{example} 2078 | \end{option} 2079 | 2080 | \begin{option}{delims-frac} 2081 | \begin{values}[default = (~)] 2082 | \meta{left delimiter}\meta{right delimiter} 2083 | \end{values} 2084 | Sets delimiters used around the fraction in the derivative. These delimiters are used when the slash argument is absent and \keyval[cat=misc]{frac}{true}, assuming \keyval{switch-/}{false}. The key's default delimiters are parentheses. 2085 | \begin{example} 2086 | \pdv[delims-frac=||, frac]{f}{x,y} \\ 2087 | \pdv*[delims-frac=||, frac=true]{y}{x} 2088 | \end{example} 2089 | \end{option} 2090 | 2091 | \begin{option}{delims-frac-/} 2092 | \begin{values}[default = (~)] 2093 | \meta{left delimiter}\meta{right delimiter} 2094 | \end{values} 2095 | Sets delimiters used around the fraction in the derivative. These delimiters are used when the slash argument is present and \keyval[cat=misc]{frac}{true}, assuming \keyval{switch-/}{false}. The key's default delimiters are parentheses. 2096 | \begin{example} 2097 | \pdv[delims-frac-/=\|\|, frac]{f}/{x,y} \\ 2098 | \pdv*[delims-frac-/=\|\|, frac]{f}/{x,y} 2099 | \end{example} 2100 | \end{option} 2101 | 2102 | \subsubsection*{Math spacing and separators} 2103 | %The options in this subsection insert additional horizontal math space or separators in specific positions. The equations below illustrates where the space is inserted for each option:%TODO - math space should probably be seperator instead 2104 | %\begin{align*} 2105 | % \begin{gathered} 2106 | % \frac{ \partial }{ \partial x } \ms{frac-fun} f \\ 2107 | % \frac{ \partial^{ \ms{inf-ord} 2 } f }{ \partial x^{ \ms{var-ord} 2 } } 2108 | % \end{gathered} 2109 | % && 2110 | % \begin{gathered} 2111 | % \frac{ \partial \ms{inf-fun} f }{ \partial \ms{inf-var} x } \\ 2112 | % \frac{ \partial^3 \ms{ord-fun} f }{ \partial x^2 \ms{ord-inf} \partial y } 2113 | % \end{gathered} 2114 | % && 2115 | % \begin{gathered} 2116 | % \frac{ \partial^2 f }{ \partial x \ms{var-inf} \partial y } \\ 2117 | % \mleft( \frac{ \partial f}{ \partial x } \mright)_{ \ms{eval-sb} x_1}^{ \ms{eval-sp} x_2} 2118 | % \end{gathered} 2119 | %\end{align*} 2120 | %where it have been split into six to give a better overview. Here $\ms{\dots}$ means the value given to the option \key[index=false]{sep-\meta{\dots}}. Some of the math spaces shown above are only used when \keyval[index=false]{style-var}{multiple}. Additionally, when the option \keyval[index=false]{style-var}{single} is used then the following math space is used in the denominator 2121 | %%Please note that some of the math spaces shown above are only used when \key[index=false]{style-var} is set to \val{multiple}. Additionally, when \key[index=false]{style-var} is set to \val{single}, the following math space is used in the denominator: 2122 | %\begin{equation*} 2123 | % \frac{\partial(f, g)}{\partial(x \ms{var-var} y)} 2124 | %\end{equation*} 2125 | %where the Jacobian is used as an example. 2126 | 2127 | \begin{option}{sep-inf-ord} 2128 | \begin{values}[default = 0] 2129 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2130 | \end{values} 2131 | Sets the separator that is inserted to the left of the infinitesimal's power when the (mixed) order \emph{is different} from \num{1}. The default value corresponds to \val{\default} \texttt{mu}. 2132 | \begin{example} 2133 | \pdv[sep-inf-ord=\here]{f}{x,y} \\ 2134 | \pdv[sep-inf-ord=\here, order=2]{f}!{x,y} \\ 2135 | \pdv[sep-inf-ord=\here, order=2]{f}/!{x,y} 2136 | \end{example} 2137 | \end{option} 2138 | 2139 | \begin{option}{sep-inf-fun} 2140 | \begin{values}[default = 0] 2141 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2142 | \end{values} 2143 | Sets the separator that is inserted between the infinitesimal and the function when the (mixed) order \emph{is equal} to \num{1}. The space is only inserted when a non-blank function is printed \emph{in the numerator}. The default value corresponds to \val{\default} \texttt{mu}. 2144 | \begin{example} 2145 | \pdv[sep-inf-fun=\here]{f}{x} 2146 | \end{example} 2147 | \end{option} 2148 | 2149 | \begin{option}{sep-ord-fun} 2150 | \begin{values}[default = 0] 2151 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2152 | \end{values} 2153 | Sets the separator that is inserted between the function and the infinitesimal's order when the order \emph{is different} from \num{1}. The space is only inserted when a non-blank function is printed \emph{in the numerator}. The default value corresponds to \val{\default} \texttt{mu}. 2154 | \begin{example} 2155 | \pdv[sep-ord-fun=\here]{f}{x,y} 2156 | \end{example} 2157 | \end{option} 2158 | 2159 | \begin{option}{sep-frac-fun}[new = v1.0] 2160 | \begin{values}[default = 0] 2161 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2162 | \end{values} 2163 | Sets the separator that is inserted between the fractional part of the derivative and the function when a non-blank function is printed \emph{next to the derivative}. The default value corresponds to \val{\default} \texttt{mu}. 2164 | \begin{example} 2165 | \pdv*[sep-frac-fun=\here]{f}{x,y} 2166 | \end{example} 2167 | \end{option} 2168 | 2169 | \begin{option}{sep-inf-var} 2170 | \begin{values}[default = 0] 2171 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2172 | \end{values} 2173 | Sets the separator that is inserted between the infinitesimal and the following non-blank variable. In shorthand mode, the order must also \emph{be different} from \num{1}. The default value corresponds to \val{\default} \texttt{mu}. 2174 | \begin{example} 2175 | \pdv[sep-inf-var=\here, order=2]{f}{x,y} \\ 2176 | \pdv[sep-inf-var=\here, order=2]{f}!{x,y} \\ 2177 | \pdv[sep-inf-var=\here, order=2]{f}/!{x,y} 2178 | \end{example} 2179 | \end{option} 2180 | 2181 | \begin{option}{sep-var-ord} 2182 | \begin{values}[default = 0] 2183 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2184 | \end{values} 2185 | Sets the separator that is inserted to the left of the variable's power when its order \emph{is different} from \num{1}. The default value corresponds to \val{\default} \texttt{mu}. 2186 | %This key sets the separator that is inserted in a variable's power left to the order. The space is only inserted when the order \emph{is different} from \num{1}. The key's default value corresponds to \val{\default} \texttt{mu}. 2187 | \begin{example} 2188 | \pdv[sep-var-ord=\here, order=n]{f}{x,y} 2189 | \end{example} 2190 | \end{option} 2191 | 2192 | \begin{option}{sep-var-inf} 2193 | \begin{values}[default = \cs{mathop}\{\}\cs{!}] 2194 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2195 | \end{values} 2196 | Sets the separator that is inserted between a variable and the following infinitesimal when more than one \emph{non-blank} variables are given. In fraction mode, it is also required that the variable's order \emph{is equal} to \num{1}. The default value is \val{\default}. 2197 | \begin{example} 2198 | \pdv[sep-var-inf=\here, order=n]{f}{x,y,z}\\ 2199 | \pdv[sep-var-inf=\here, order=n]{f}!{x,y,z}\\ 2200 | \pdv[sep-var-inf=\here, order=n]{f}/!{x,y,z} 2201 | \end{example} 2202 | \end{option} 2203 | 2204 | \begin{option}{sep-ord-inf} 2205 | \begin{values}[default = \cs{mathop}\{\}\cs{!}] 2206 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2207 | \end{values} 2208 | Sets the separator that is inserted between an order and the following infinitesimal when more than one \emph{non-blank} variables are given. In fraction mode, it is also required that the variable's order \emph{is different} from \num{1}. The default value is \val{\default}. 2209 | \begin{example} 2210 | \pdv[sep-ord-inf=\here, order=n]{f}{x,y,z} 2211 | \end{example} 2212 | \end{option} 2213 | 2214 | \begin{option}{sep-ord-ord}[new = v1.3] 2215 | \begin{values}[default = {{,}}] 2216 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2217 | \end{values} 2218 | Sets the separator that is inserted between two orders when more than one \emph{non-blank} variables are given in shorthand notation when it is set to \val{single}. The default value is a comma. 2219 | \begin{example} 2220 | \odv[sep-ord-ord=\here, order={n,2}]{f}/!{x,y} 2221 | \end{example} 2222 | \end{option} 2223 | 2224 | \begin{option}{sep-ord-var}[new = v1.3] 2225 | \begin{values}[default = 0] 2226 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2227 | \end{values} 2228 | Sets the separator that is inserted between an order and the following variable in shorthand notation when it is set to \val{multiple}. The default value corresponds to \val{\default} \texttt{mu}. 2229 | \begin{example} 2230 | \odv[sep-ord-var=\here, order=n]{f}!{x,y} 2231 | \end{example} 2232 | \end{option} 2233 | 2234 | \begin{option}{sep-var-var}[new = v1.0] 2235 | \begin{values}[default = {{,}}] 2236 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2237 | \end{values} 2238 | Sets the separator that is inserted between two variables when more than one \emph{non-blank} variables are given in shorthand notation when it is set to \val{single}. The default value is a comma. 2239 | \begin{example} 2240 | \odv[sep-var-var=\here]{f}{x,y} \\ 2241 | \odv[sep-var-var=\here]{f}/!{x,y} 2242 | \end{example} 2243 | \end{option} 2244 | 2245 | \begin{option}{sep-eval-sb} 2246 | \begin{values}[default = 0] 2247 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2248 | \end{values} 2249 | Sets the separator that is inserted in the evaluation subscript left to the point of evaluation when a \emph{non-blank} subscript is given. The default value corresponds to \val{\default} \texttt{mu}. 2250 | \begin{example} 2251 | \pdv[sep-eval-sb=\here]{f}{x,y}_{(x_1,y_1)} 2252 | \end{example} 2253 | \end{option} 2254 | 2255 | \begin{option}{sep-eval-sp} 2256 | \begin{values}[default = 0] 2257 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2258 | \end{values} 2259 | Sets the separator that is inserted in the evaluation superscript left to the point of evaluation when a \emph{non-blank} superscript is given. The default value corresponds to \val{\default} \texttt{mu}. 2260 | \begin{example} 2261 | \pdv[sep-eval-sp=\here]{f}{x,y}^{(x_2,y_2)} 2262 | \end{example} 2263 | \end{option} 2264 | 2265 | \subsubsection*{Switches} 2266 | 2267 | \begin{option}*{switch-*} 2268 | \begin{values}[default = false] 2269 | true, false 2270 | \end{values} 2271 | The effect of the star argument can be toggled with the value \val{true}. 2272 | %That is, the function is typeset next to the fraction when the star is absent and in the numerator when the star is present. 2273 | For example, compare below where the option is disabled (\val{false}) and enabled (\val{true}). The default value is \val{\default}. 2274 | \begin{example} 2275 | \pdv[switch-*=false]{f}{x,y} \\ 2276 | \pdv[switch-*=true]{f}{x,y} 2277 | \end{example} 2278 | \end{option} 2279 | 2280 | \begin{option}{switch-/} 2281 | \begin{values}[default = false] 2282 | true, false 2283 | \end{values} 2284 | The effect of the slash argument can be toggled with the value \val{true}. 2285 | %That is, the derivative is typeset with the fraction set by \key{style-frac-/} when the slash is absent and with the fraction set by \key{style-frac} when the slash is present. 2286 | For example, compare below where the option is disabled (\val{false}) and enabled (\val{true}). The default value is \val{\default}. 2287 | \begin{example} 2288 | \pdv[switch-/=false]{f}{x,y} \\ 2289 | \pdv[switch-/=true]{f}{x,y} 2290 | \end{example} 2291 | \end{option} 2292 | 2293 | \begin{option}{switch-!}[new = 1.3] 2294 | \begin{values}[default = false] 2295 | true, false 2296 | \end{values} 2297 | The effect of the exclamation mark argument can be toggled with the value \val{true}. 2298 | %That is, the derivative is in shorthand mode the exclamation mark is absent and in fraction mode when the exclamation is present. 2299 | For example, compare below where the option is disabled (\val{false}) and enabled (\val{true}). The default value is \val{\default}. 2300 | \begin{example} 2301 | \pdv[switch-!=false]{f}{x,y} \\ 2302 | \pdv[switch-!=true]{f}{x,y} 2303 | \end{example} 2304 | \end{option} 2305 | 2306 | \begin{option}{switch-sort}[new = 1.2] 2307 | \begin{values}[default = true] 2308 | true, false 2309 | \end{values} 2310 | This options disables (\val{false}) and enables (\val{true}) the sorting algorithm behind the mixed order. The sorting algorithm is only used/available in fraction mode when it is \val{multiple}. When disabled, the terms in the mixed order are arranged according to their first appearance in \keyval*[cat=misc,index=false]{order}{\dots}. Compare below where the option is disabled (\val{false}) and enabled (\val{true}). The default value is \val{\default}. 2311 | %When the value \val{true} is given, the mixed order sorting algorithm is activated, applying the methods specified in \keyval*{sort-method}{\dots}. Conversely, when the value \val{false} is given, the sorting algorithm is deactivated, and the terms in the mixed order are arranged according to their first appearance in \keyval*{order}{\dots}. Here's a comparison example with the option enabled (\val{true}) and disabled (\val{false}). 2312 | \begin{example} 2313 | \pdv[switch-sort=false, order={a+b,2kn-d,2-2b}]{f}{x,y,z} \\ 2314 | \pdv[switch-sort=true, order={a+b,2kn-d,2-2b}]{f}{x,y,z} 2315 | \end{example} 2316 | \end{option} 2317 | 2318 | \subsubsection*{Sort} 2319 | The keys mentioned in this subsection will be briefly described here, with a more detailed explanation provided in \cref{ssec:overall_order}. 2320 | 2321 | \begin{option}{sort-method}[updated = v1.2] 2322 | \begin{values}[default = {sign, symbol, abs}] 2323 | abs, lexical, number, sign, symbol 2324 | \end{values} 2325 | Sets the sorting method for the mixed order using build-in algorithms. 2326 | \begin{itemize}[widest = {\val{lexical}}, leftmargin =*] 2327 | \item[\val{abs}] Sorts terms in descending order based on their absolute value. 2328 | \item[\val{lexical}] Sorts terms alphabetically in lexicographical ascending order. 2329 | \item[\val{number}] Sorts terms in descending order based on their numerical value. 2330 | \item[\val{sign}] Sorts terms by their sign, placing positive terms before the negative terms. 2331 | \item[\val{symbol}] Sorts terms in descending order based on their symbolic length. 2332 | \end{itemize} 2333 | This option accepts a comma-separated list of values, allowing up to three values. For example: 2334 | \begin{example} 2335 | \pdv[sort-method=abs, order={kn-c,2a-3b}]{f}{x,y} \\ 2336 | \pdv[sort-method=lexical, order={kn-c,2a-3b}]{f}{x,y} \\ 2337 | \pdv[sort-method=number, order={kn-c,2a-3b}]{f}{x,y} \\ 2338 | \pdv[sort-method=symbol, order={kn-c,2a-3b}]{f}{x,y} \\ 2339 | \pdv[sort-method=sign, order={kn-c,2a-3b}]{f}{x,y} \\ 2340 | \pdv[sort-method={sign,abs}, order={kn-c,2a-3b}]{f}{x,y} \\ 2341 | \pdv[sort-method={sign,symbol,abs}, order={kn-c,2a-3b}]{f}{x,y} 2342 | \end{example} 2343 | Notice the different term ordering achieved with each method. For a more detailed explanation of this key, see \cref{ssec:sort-method} for more information. The default value uses the three algorithms \val{\default}. 2344 | \end{option} 2345 | 2346 | \begin{option}{sort-numerical}[updated = v1.0] 2347 | \begin{values}[default = auto] 2348 | auto, first, last, symbolic 2349 | \end{values} 2350 | Determines the placement of the numerical term\footnote{The numerical term refers to the sum of all orders that consist solely of numbers and do not include any symbols.\label{foot:numerical-term}} in the mixed order. The placement options are as follows: 2351 | \begin{itemize}[widest=\val{symbolic}, leftmargin=*] 2352 | \item[\val{first}] Always places the numerical term as the first term in the mixed order. 2353 | \item[\val{last}] Always places the numerical term as the last term in the mixed order. 2354 | \item[\val{auto}] After sorting, the numerical term is automatically positioned based on the sign of the first symbolic term. If positive, the numerical term is placed last. If negative, the numerical term is placed first. 2355 | \item[\val{symbolic}] Treats the numerical term as a symbolic term with a symbolic length of zero and sorts it alongside all other terms. 2356 | \end{itemize} 2357 | Here are some examples to illustrate the different placements of the numerical term: 2358 | \begin{example} 2359 | \pdv[sort-numerical=first, order={n,2}]{f}{x,y} \\ 2360 | \pdv[sort-numerical=last, order={-n,2}]{f}{x,y} \\ 2361 | \pdv[sort-numerical=auto, order={n,2}]{f}{x,y} \\ 2362 | \pdv[sort-numerical=auto, order={-n,2}]{f}{x,y} \\ 2363 | \pdv[sort-numerical=symbolic, order={2+n,-a}]{f}{x,y} 2364 | \end{example} 2365 | This key is further described in \cref{ssec:sort-numerical}. The default value is \val{\default}. 2366 | \end{option} 2367 | 2368 | \begin{option}{sort-abs-reverse} 2369 | \begin{values}[default = false] 2370 | true, false 2371 | \end{values} 2372 | When the value \val{true} is used with this option, the sorting order is reversed to ascending order. See \cref{ssec:sort-reverse} for more information. 2373 | \begin{example} 2374 | \pdv[sort-abs-reverse=false, sort-method=abs, order=2a-3b]{f}{x} \\ 2375 | \pdv[sort-abs-reverse=true, sort-method=abs, order=2a-3b]{f}{x} 2376 | \end{example} 2377 | \end{option} 2378 | 2379 | \begin{option}{sort-lexical-reverse}[new = v1.2] 2380 | \begin{values}[default = false] 2381 | true, false 2382 | \end{values} 2383 | When the value \val{true} is used with this option, the sorting order is reversed to lexicographical descending order. See \cref{ssec:sort-reverse} for more information. 2384 | \begin{example} 2385 | \pdv[sort-lexical-reverse=false, sort-method=lexical, order=a+b]{f}{x} \\ 2386 | \pdv[sort-lexical-reverse=true, sort-method=lexical, order=a+b]{f}{x} 2387 | \end{example} 2388 | \end{option} 2389 | 2390 | \begin{option}{sort-number-reverse}[new = v1.0] 2391 | \begin{values}[default = false] 2392 | true, false 2393 | \end{values} 2394 | When the value \val{true} is used with this option, the sorting order is reversed to ascending order. See \cref{ssec:sort-reverse} for more information. 2395 | \begin{example} 2396 | \pdv[sort-number-reverse=false, sort-method=number, order=2a-3b]{f}{x} \\ 2397 | \pdv[sort-number-reverse=true, sort-method=number, order=2a-3b]{f}{x} 2398 | \end{example} 2399 | \end{option} 2400 | 2401 | \begin{option}{sort-sign-reverse} 2402 | \begin{values}[default = false] 2403 | true, false 2404 | \end{values} 2405 | When the value \val{true} is used with this option, the sorting order is reversed, placing negative terms before the positive terms. See \cref{ssec:sort-reverse} for more information. 2406 | \begin{example} 2407 | \pdv[sort-sign-reverse=false, sort-method=sign, order=a-b]{f}{x} \\ 2408 | \pdv[sort-sign-reverse=true, sort-method=sign, order=a-b]{f}{x} 2409 | \end{example} 2410 | \end{option} 2411 | 2412 | \begin{option}{sort-symbol-reverse} 2413 | \begin{values}[default = false] 2414 | true, false 2415 | \end{values} 2416 | When the value \val{true} is used with this option, the sorting order is reversed to ascending order. See \cref{ssec:sort-reverse} for more information. 2417 | \begin{example} 2418 | \pdv[sort-symbol-reverse=false, sort-method=symbol, order=ab+c]{f}{x} \\ 2419 | \pdv[sort-symbol-reverse=true, sort-method=symbol, order=ab+c]{f}{x} 2420 | \end{example} 2421 | \end{option} 2422 | 2423 | \subsubsection*{Miscellaneous} 2424 | 2425 | \begin{option}*{fun}[cat=misc, new = v1.0] 2426 | \begin{values}[default = false] 2427 | true, false 2428 | \end{values} 2429 | This option allows you to add (\val{true}) or remove (\val{false}) delimiters around the function. Note that if the option is not explicitly set, it is considered equivalent to \keyval[cat=misc,index=false]{fun}{true}. By default, the value is \val{\default}. 2430 | \begin{example} 2431 | \pdv[fun=false]{f}{x} \\ 2432 | \pdv[fun=true]{f}{x} \\ 2433 | \pdv[fun]{f}{x} 2434 | \end{example} 2435 | %Without setting the option to a value is equivalent to setting it to \val{true} as seen above. 2436 | \end{option} 2437 | 2438 | \begin{option}{frac}[cat=misc, new = v1.0] 2439 | \begin{values}[default = false] 2440 | true, false 2441 | \end{values} 2442 | This option allows you to add (\val{true}) or remove (\val{false}) delimiters around the fractional part of the derivative. Note that if the option is not explicitly set, it is considered equivalent to \keyval[cat=misc,index=false]{frac}{true}. By default, the value is \val{\default}. 2443 | \begin{example} 2444 | \pdv[frac=false]{f}{x} \\ 2445 | \pdv[frac=true]{f}{x} \\ 2446 | \pdv*[frac=true]{f}{x} \\ 2447 | \pdv[frac]{f}{x} 2448 | \end{example} 2449 | \end{option} 2450 | 2451 | \begin{option}{var}[cat=misc, new = v1.0] 2452 | \begin{values}[default=none] 2453 | none, all, \meta{cs-numbers} 2454 | \end{values} 2455 | This option allows you to add or remove delimiters around the variables. The value \val{all} adds delimiters around all variables and \val{none} removed all delimiters. If only specific variables require delimiters, you can use \meta{cs-numbers}. For example, \keyval*[cat=misc,index=false]{var}{1,3} adds delimiters around the first and third variables. Note that if the option is not explicitly set, it is considered equivalent to \keyval[cat=misc,index=false]{var}{all}. By default, the value is \val{\default}. 2456 | \begin{example} 2457 | \pdv[var=none]{f}{x,y,z,t} \\ 2458 | \pdv[var={1,3}]{f}{x,y,z,t} \\ 2459 | \pdv[var=all]{f}{x,y,z,t} \\ 2460 | \pdv[var]{f}{x,y,z,t} 2461 | \end{example} 2462 | \end{option} 2463 | 2464 | \begin{option}{order, ord}[cat=misc, new = v1.0] 2465 | \begin{values}[default = 1] 2466 | \marg{cs-orders} 2467 | \end{values} 2468 | Sets the order of differentiation for each variable as a comma separated list of values. 2469 | \begin{example} 2470 | \pdv[order={2,3}]{f}{x,y,z} \\ 2471 | \pdv[order={\beta,a,n+2a}]{f}{x,y,z} \\ 2472 | \pdv[order={2,n^2,n^2-1}]{f}{x,y,z} \\ 2473 | \pdv[order={3/2-n/3,n/2,1/3}]{f}{x,y,z} 2474 | \end{example} 2475 | \end{option} 2476 | 2477 | \begin{option}{mixed-order, mixord}[cat=misc, new = v1.0] 2478 | \begin{values}[default = 1] 2479 | \marg{mixed order} 2480 | \end{values} 2481 | This option allows you to manually specify the mixed order of differentiation, overriding the automatically calculated value based on the orders set by \keyval[cat=misc]{order}{\marg{orders}}. In cases where the automatic calculation fails or when a different form is preferred, you can use this option to set the desired mixed order. 2482 | \begin{example} 2483 | \pdv[order={n+3k, n-k}]{f}{x,y} \\ 2484 | \pdv[order={n+3k, n-k}, mixed-order={2(n+k)}]{f}{x,y} 2485 | \end{example} 2486 | \end{option} 2487 | 2488 | \subsection{Differential options} \label{ssec:options_inf} 2489 | The options in this subsection are available for customizing the behaviour of differentials defined by the package and you. 2490 | 2491 | \subsubsection*{Style} 2492 | 2493 | \begin{option}*{style-inf} 2494 | \begin{values}[default = d] 2495 | \meta{math-font-style}\meta{infinitesimal} 2496 | \end{values} 2497 | Sets the infinitesimal used in the differential. The default infinitesimal is a plain \default. 2498 | \begin{example} 2499 | \odif[style-inf=\mathbf{d}]{x_1,x_2,x_3} 2500 | \end{example} 2501 | \end{option} 2502 | 2503 | \begin{option}{style-var}[updated=1.3] 2504 | \begin{values}[default = multiple] 2505 | single, multiple, mixed 2506 | \end{values} 2507 | This options determines the shorthand notation of the differential when the star argument is absent assuming \keyval{switch-*}{false}. 2508 | \begin{itemize}[widest = {\val{multiple}}, leftmargin =*] 2509 | \item[\val{single}] Creates a single differential with variables as subscripts and orders as superscripts. 2510 | \item[\val{multiple}] Creates a separate differential for each variable. 2511 | \item[\val{mixed}] Creates a separate differential for each variable but with variables as subscripts and orders as superscripts. 2512 | \end{itemize} 2513 | \begin{example} 2514 | \odif[style-var=multiple, order={n,1,2}]{x,y,z,t} \\ 2515 | \odif[style-var=single, order={n,1,2}]{x,y,z,t} \\ 2516 | \odif[style-var=mixed, order={n,1,2}]{x,y,z,t} 2517 | \end{example} 2518 | \end{option} 2519 | 2520 | \begin{option}{style-var-*}[updated=1.3] 2521 | \begin{values}[default = single] 2522 | single, multiple, mixed 2523 | \end{values} 2524 | This option behaves identically to \key{style-var}, however it is used when the star argument is present assuming \keyval{switch-*}{false}. 2525 | \end{option} 2526 | 2527 | \subsubsection*{Scaling} 2528 | 2529 | \begin{option}{scale-var} 2530 | \begin{values}[default = auto] 2531 | auto, none, big, Big, bigg, Bigg 2532 | \end{values} 2533 | Sets the size of the delimiters used around the variables specified by the \keyval*[cat=misc,index=false]{var}{\dots} option when the star argument is absent assuming \keyval{switch-*}{false}. The default behaviour is to automatically scale the delimiters. 2534 | \begin{example} 2535 | \odif[scale-var=none, var]{r,\theta,\varphi}\\ 2536 | \odif[scale-var=Big, var]{r,\theta,\varphi} 2537 | \end{example} 2538 | \end{option} 2539 | 2540 | \begin{option}{scale-var-*} 2541 | \begin{values}[default = auto] 2542 | auto, none, big, Big, bigg, Bigg 2543 | \end{values} 2544 | Sets the size of the delimiters used around the variables specified by the \keyval*[cat=misc,index=false]{var}{\dots} option when the star argument is present assuming \keyval{switch-*}{false}. The default behaviour is to automatically scale the delimiters. 2545 | \begin{example} 2546 | \odif*[scale-var-*=auto, var]{r,\theta,\varphi}\\ 2547 | \odif*[scale-var-*=big, var]{r,\theta,\varphi} 2548 | \end{example} 2549 | \end{option} 2550 | 2551 | \subsubsection*{Delimiters} 2552 | 2553 | \begin{option}{delims-var} 2554 | \begin{values}[default = (~)] 2555 | \meta{left delimiter}\meta{right delimiter} 2556 | \end{values} 2557 | Sets the delimiters used around the variables specified by the \keyval*[cat=misc,index=false]{var}{\dots} option when the star argument is absent assuming \keyval{switch-*}{false}. The default delimiters are parentheses. 2558 | \begin{example} 2559 | \odif[delims-var=\{\}, var]{x,y}\\ 2560 | \odif[delims-var=[], var]{x,y} 2561 | \end{example} 2562 | \end{option} 2563 | 2564 | \begin{option}{delims-var-*} 2565 | \begin{values}[default = (~)] 2566 | \meta{left delimiter}\meta{right delimiter} 2567 | \end{values} 2568 | Sets the delimiters used around the variables specified by the \keyval*[cat=misc,index=false]{var}{\dots} option when the star argument is present assuming \keyval{switch-*}{false}. The default delimiters are parentheses. 2569 | \begin{example} 2570 | \odif*[delims-var-*=\|\|, var]{x,y}\\ 2571 | \odif*[delims-var-*=\langle\rangle, var]{x,y} 2572 | \end{example} 2573 | \end{option} 2574 | 2575 | \subsubsection*{Math spacing and separators} 2576 | %The options in this subsection inserts additional horizontal math space in specific positions. The equations below illustrates where the space is inserted for each option:%TODO - math space should probably be seperator instead 2577 | %\begin{align*} 2578 | % \begin{gathered} 2579 | % \partial \ms{inf-var} x \ms{var-inf} \partial y \\ 2580 | % \partial^{ \ms{inf-ord} 2 } \ms{ord-var} x 2581 | % \end{gathered} 2582 | % && 2583 | % \begin{gathered} 2584 | % \ms{begin} \partial x \ms{end} \\ 2585 | % \partial^{ 2\ms{ord-ord} 2 }_{ x \ms{var-var} y } 2586 | % \end{gathered} 2587 | %\end{align*} 2588 | 2589 | \begin{option}{sep-begin} 2590 | \begin{values}[default = \cs{mathop}\{\}\cs{!}] 2591 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2592 | \end{values} 2593 | Sets the separator that is inserted at the beginning of the expression. The default value is \val{\default}. 2594 | \begin{example} 2595 | \odif[sep-begin=\here]{x,y,z} 2596 | \end{example} 2597 | \end{option} 2598 | 2599 | \begin{option}{sep-inf-ord} 2600 | \begin{values}[default = 0] 2601 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2602 | \end{values} 2603 | Sets the separator that is inserted to the left of the infinitesimal's power when the order \emph{is different} from \num{1}. The default value corresponds to \val{\default} \texttt{mu}. 2604 | \begin{example} 2605 | \odif[sep-inf-ord=\here, order=2]{x,y} 2606 | \end{example} 2607 | \end{option} 2608 | 2609 | \begin{option}{sep-inf-var} 2610 | \begin{values}[default = 0] 2611 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2612 | \end{values} 2613 | Sets the separator that is inserted between the infinitesimal and the following non-blank variable when the associated order \emph{is equal} to \num{1}. The key's default value corresponds to \val{\default} \texttt{mu}. 2614 | \begin{example} 2615 | \odif[sep-inf-var=\here, order=2]{x,y} 2616 | \end{example} 2617 | \end{option} 2618 | 2619 | \begin{option}{sep-ord-var} 2620 | \begin{values}[default = 0] 2621 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2622 | \end{values} 2623 | Sets the separator that is inserted between an order and the following non-blank variable when the order \emph{is different} from \num{1}. This option is only available when the style is set to \val{multiple}. The default value corresponds to \val{\default} \texttt{mu}. 2624 | \begin{example} 2625 | \odif[sep-ord-var=\here, order=2]{x,y} 2626 | \end{example} 2627 | \end{option} 2628 | 2629 | \begin{option}{sep-var-inf} 2630 | \begin{values}[default = \cs{mathop}\{\}\cs{!}] 2631 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2632 | \end{values} 2633 | Sets the separator that is inserted between a non-blank variable and the following infinitesimal when more than one non-blank variables are given. The default value is \val{\default}. 2634 | \begin{example} 2635 | \odif[sep-var-inf=\here]{x,y} 2636 | \end{example} 2637 | \end{option} 2638 | 2639 | \begin{option}{sep-var-var} 2640 | \begin{values}[default = {{,}}] 2641 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2642 | \end{values} 2643 | Sets the separator that is inserted between two variables when more than one non-blank variables are given. This option is only available when the style is set to \val{single}. The default value is a comma. 2644 | \begin{example} 2645 | \odif*[sep-var-var=\here]{x,y} 2646 | \end{example} 2647 | \end{option} 2648 | 2649 | \begin{option}{sep-ord-ord} 2650 | \begin{values}[default = {{,}}] 2651 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2652 | \end{values} 2653 | Sets the separator that is inserted between two orders that are both not equal to \num{1}. This option is only available when the style is set to \val{single}. The default value is a comma. 2654 | \begin{example} 2655 | \odif*[sep-ord-ord=\here, order={2,n}]{x,y} 2656 | \end{example} 2657 | \end{option} 2658 | 2659 | \begin{option}{sep-end} 2660 | \begin{values}[default = 0] 2661 | \meta{cs-number}, \marg{mspace}, \marg{delimiter} 2662 | \end{values} 2663 | Sets the separator that is inserted at the end of the expression. The default value corresponds to \val{\default} \texttt{mu}. 2664 | \begin{example} 2665 | \odif[sep-end=\here]{x,y} 2666 | \end{example} 2667 | \end{option} 2668 | 2669 | \subsubsection*{Switches} 2670 | 2671 | \begin{option}*{switch-*} 2672 | \begin{values}[default = false] 2673 | true, false 2674 | \end{values} 2675 | The effect of the star argument can be toggled with the value \val{true}. For example, compare below where the option is disabled (\val{false}) and enabled (\val{true}). The default value is \val{\default}. 2676 | \begin{example} 2677 | \odif[switch-*=false]{x,y,z,t} \\ 2678 | \odif[switch-*=true]{x,y,z,t} 2679 | \end{example} 2680 | \end{option} 2681 | 2682 | \subsubsection*{Miscellaneous} 2683 | 2684 | \begin{option}*{var}[cat=misc] 2685 | \begin{values}[default=none] 2686 | none, all, \meta{cs-numbers} 2687 | \end{values} 2688 | This option allows you to add or remove delimiters around the variables. The value \val{all} adds delimiters around all variables and \val{none} removed all delimiters. If only specific variables require delimiters, you can use \meta{cs-numbers}. For example, \keyval*[cat=misc,index=false]{var}{1,3} adds delimiters around the first and third variables. Note that if the option is not explicitly set, it is considered equivalent to \val{all}. By default, the value is \val{\default}. 2689 | \begin{example} 2690 | \odif[var=none]{x,y,z,t} \\ 2691 | \odif[var={1,3}]{x,y,z,t} \\ 2692 | \odif[var=all]{x,y,z,t} \\ 2693 | \odif[var]{x,y,z,t} 2694 | \end{example} 2695 | \end{option} 2696 | 2697 | \begin{option}{order, ord}[cat=misc] 2698 | \begin{values}[default = 1] 2699 | \marg{cs-orders} 2700 | \end{values} 2701 | Sets the order of differentiation for each variable as a comma separated list of values. 2702 | \begin{example} 2703 | \odif[order={2,3}]{x,y,z} \\ 2704 | \odif[order={\beta,a,n+2a}]{x,y,z} 2705 | \end{example} 2706 | \end{option} 2707 | 2708 | \subsection{All derivatives and differentials} \label{ssec:both_options} 2709 | The options in this subsection are applied to all derivatives and differentials because they define settings that should be consistent regardless of the specific derivative or differential. These options can be accessed using the command \macro{\derivset}[\narg{all},\oarg{key=value}]. 2710 | 2711 | The options in this subsection are applied to all derivatives and differential because some options should be consisting regardless of the derivative and differential. The options are accessed using \macro{\derivset}[\narg{all},\oarg{key=value}]. 2712 | \begin{example}[result=false] 2713 | \derivset{all}[key=value] 2714 | \end{example} 2715 | 2716 | \begin{option}{scale-auto}[updated = v1.1] 2717 | \begin{values}[default = {leftright or mleftmright\req}] 2718 | leftright, mleftmright\req 2719 | \end{values} 2720 | Sets the automatic delimiter scaling commands. The value \val{leftright} sets them as \cs{left} and \cs{right} while \val{mleftmright} sets them as \cs{mleft} and \cs{mright} from the \pkg{mleftrigth} package. The default value is \val{leftright} unless \pkg{mleftright} is loaded, in which case it is \val{mleftmright}. 2721 | \begin{example} 2722 | \derivset{all}[scale-auto=leftright] a \pdv[frac]{f}{x} a\\ 2723 | \derivset{all}[scale-auto=mleftmright] a \pdv[frac]{f}{x} a 2724 | \end{example} 2725 | Notice the space difference between the a's and the parentheses in the two equations. 2726 | \end{option} 2727 | 2728 | 2729 | \clearpage 2730 | \section{Defining variants} \label{sec:defvar} 2731 | This section goes into detail on how to define derivative and differential variants based on the package's internal commands. The \mypackage{} package provides a \latex2-based approach to defining derivatives and differentials. 2732 | 2733 | \subsection{Derivative variant} \label{ssec:defvar_dv} 2734 | 2735 | \begin{function}*{\NewDerivative, \RenewDerivative, \ProvideDerivative, \DeclareDerivative} 2736 | \begin{syntax} 2737 | \meta{control-sequence}, \marg{infinitesimal}, \oarg{key=value} 2738 | \end{syntax} 2739 | This family of commands is used to define a derivative variant with the macro name \arg{1}. %The new derivative will use the infinitesimal \arg{2} and inherit the package's default settings given in \cref{ssec:options_dv}, which can be overwritten with \arg{3}. The difference between the commands is as follows: 2740 | \begin{itemize} 2741 | \item \macro{1} will issue an error if \arg{1} has already been defined. 2742 | \item \macro{2} will issue an error if \arg{1} has not previously been defined. 2743 | \item \macro{3} will define \arg{1} if it does not have an existing definition. It will not issue any errors. 2744 | \item \macro{4} will always define the \arg{1} with the new definition regardless of whether it already exists. 2745 | \end{itemize} 2746 | Examples of their use can be found in \cref{sec:derivative}. 2747 | 2748 | \begin{argument}{1} 2749 | The first argument specifies the macro name of the derivative being defined. 2750 | \end{argument} 2751 | 2752 | \begin{argument}{2} 2753 | The second argument sets the infinitesimal of the derivative \arg{1}. It is equivalent to setting \keyval{style-inf}{\arg{2}}. 2754 | \end{argument} 2755 | 2756 | \begin{argument}{3} 2757 | The optional argument accepts a comma-separated list of \emph{key=value} pairs, allowing you to override the package's default values for the keys given. If the optional argument is omitted, the derivative will use the package's default settings. 2758 | \end{argument} 2759 | \end{function} 2760 | 2761 | \subsection{Differential variant} \label{ssec:defvar_inf} 2762 | 2763 | \begin{function}*{\NewDifferential, \RenewDifferential, \ProvideDifferential, \DeclareDifferential} 2764 | \begin{syntax} 2765 | \meta{control-sequence}, \marg{infinitesimal}, \oarg{key=value} 2766 | \end{syntax} 2767 | This family of commands is used to define a differential variant with the macro name \arg{1}. %The new differential will use the infinitesimal \arg{2} and inherit the package's default settings given in \cref{ssec:options_inf}, which can be overwritten with \arg{3}. The difference between the commands is as follows: 2768 | 2769 | \begin{itemize} 2770 | \item \macro{1} will issue an error if \arg{1} has already been defined. 2771 | \item \macro{2} will issue an error if \arg{1} has not previously been defined. 2772 | \item \macro{3} will define \arg{1} if it does not have an existing definition. It will not issue any errors. 2773 | \item \macro{4} will always define the \arg{1} with the new definition regardless of whether it already exists. 2774 | \end{itemize} 2775 | Examples of their use can be found in \cref{sec:differential}. 2776 | 2777 | \begin{argument}{1} 2778 | The first argument specifies the macro name of the differential being defined. 2779 | \end{argument} 2780 | 2781 | \begin{argument}{2} 2782 | The second argument sets the infinitesimal of the differential \arg{1}. It is equivalent to setting \keyval{style-inf}{\arg{2}}. 2783 | \end{argument} 2784 | 2785 | \begin{argument}{3} 2786 | The optional argument accepts a comma-separated list of \narg{key=value} pairs, allowing you to override the package's default values for the keys given. If the optional argument is omitted, the derivative will use the package's default settings. 2787 | \end{argument} 2788 | \end{function} 2789 | 2790 | 2791 | 2792 | \clearpage 2793 | \section{The mixed order} \label{ssec:overall_order} 2794 | The algorithm used to calculate the mixed order is advanced and can handle a wide range of inputs, including numbers, symbols and fractions. It accurately parses the orders to generate the appropriate mixed order. Let's consider some examples to illustrate its capabilities: 2795 | \begin{example} 2796 | \pdv[order={n+1,2}]{f}{x,y}\\ 2797 | \pdv[order={n+1,2n}]{f}{x,y}\\ 2798 | \pdv[order={n^2,n^2}]{f}{x,y}\\ 2799 | \pdv[order={2/n-1/2, 3/n+m/3}]{f}{x,y,z} 2800 | \end{example} 2801 | The algorithm handles these cases and calculates the mixed order correctly. However, there are certain limitations when dealing with parentheses, except for a specific case where there is a single term in the denominator. 2802 | \begin{example} 2803 | \pdv[order={2/n-1/2, 3/(2n)+m/3}]{f}{x,y}\\ 2804 | \pdv[order={(2n+m)/3, 3n+m/3}]{f}{x,y}\\ 2805 | \pdv[order={2/(2n+m), 1/(2(2n+m))}]{f}{x,y} 2806 | \end{example} 2807 | In the third equation, the mixed order doesn't make sense because the algorithm splits up the orders at $+$ and $-$ within parentheses without evaluating them correctly. For example, $2/(2n+m), 1/(2(2n+m))$ is incorrectly split into $2/(2n, m), 1/(2(2n, m))$. The same happens in the second equation. To address this limitation, the package provides the \key[cat=misc]{mixed-order} option, which overrides the incorrect output. You can specify the desired mixed order manually. 2808 | \begin{example} 2809 | \pdv[order={(2n+m)/3, 3n+m/3}, mixord=8n/3+2m/3]{f}{x,y}\\ 2810 | \pdv[order={2/(2n+m), 1/(2(2n+m))}, mixord=5/(2(2n+m))]{f}{x,y} 2811 | \end{example} 2812 | By using the \key[cat=misc]{mixed-order} option, you can ensure that the mixed order is displayed correctly, even when the algorithm's output may be incorrect or when a different form is preferred. 2813 | 2814 | \subsection{Sorting algorithms} \label{ssec:sort-method} 2815 | A unique feature of this package is that the sorting method behind the mixed order may be changed using built-in algorithms. These algorithms are designed to offer variety of ways to sort the mixed order according to ones preferences. 2816 | \begin{itemize}[widest = {\val{lexical}}, leftmargin =*] 2817 | \item[\val{abs}] Sorts terms based on their absolute value in descending order. By setting \keyval{sort-abs-reverse}{true}, terms are sorted in ascending order instead. 2818 | \item[\val{lexical}] Sorts the terms alphabetically in lexicographical order. By setting \keyval{sort-lexical-reverse}{true}, terms are sorted in reverse lexicographical order. 2819 | \item[\val{number}] Sorts terms based on their numerical value in descending order. By setting \keyval{sort-number-reverse}{true}, terms are sorted in ascending order instead. 2820 | \item[\val{sign}] Sorts terms by their sign, placing positive terms before negative terms. By setting, \keyval{sort-sign-reverse}{true}, places negative terms before positive terms. 2821 | \item[\val{symbol}] Sorts terms in descending order based on their symbolic length. By setting \keyval{sort-symbol-reverse}{true}, terms are sorted in ascending order instead. 2822 | \end{itemize} 2823 | 2824 | The sorting method allows up to three algorithms given by \keyval*{sort-method}{algorithm1, algorithm2, algorithm3}. The list of orders is primarily sorted based on algorithm 1's condition. In case of ties, algorithm 2 is used for further sorting, and so on. 2825 | 2826 | Consider the list \texttt{\{a,-c,-b,d\}} and the sorting method \keyval*{sort-method}{sign,lexical}. Initially, the \val{sign} algorithm sorts the list as \texttt{\{a,d,-c,-b\}}. However, due to ties, other valid orderings exist like \texttt{\{d,a,-c,-b\}}, \texttt{\{a,d,-b,-c\}} and \texttt{\{d,a,-b,-c\}}. Subsequently, the \val{lexical} algorithm sorts the tied values alphabetically as \texttt{\{a,d,-b,-c\}}. 2827 | 2828 | \subsubsection{Examples} 2829 | The examples below use partial derivatives with \keyval*[cat=misc]{order}{3a-3hh-2b, 4c+4gg+2ff, -5d-5ee}, along with a close-up view of the mixed order. Square brackets indicate how the terms was sorted by the applied algorithm. `Positive' and `negative', `long' and `short', and `big' and `low' refer to the \val{sign}, \val{symbol}, and \val{abs} algorithms, respectively. 2830 | 2831 | The default sorting method is \keyval*{sort-method}{sign,symbol,abs} which is used below. The \val{sign} algorithm separate the positive and negative terms. Within each group, the \val{symbol} algorithm sorts the terms based on symbolic length. Finally, In the resulting four groups, the \val{abs} algorithm sorts the terms based on absolute value. 2832 | \begin{gather*} 2833 | \pdv[sort-method = {sign,symbol,abs}, order={3a-3hh-2b, 4c+4gg+2ff, -5d-5ee}]{f}{x,y,z} \\ 2834 | \low{ 2835 | \low{ 2836 | \low{4gg}{big} + 2837 | \low[2,2]{2ff}{low} 2838 | }{long} + 2839 | \low{ 2840 | \low[1,2]{4c}{big} + 2841 | \low[1,1]{3a}{low} 2842 | }{short} 2843 | }{positive} - 2844 | \low{ 2845 | \low{ 2846 | \low[3,3]{5ee}{big} - 2847 | \low[2,2]{3hh}{low} 2848 | }{long} - 2849 | \low{ 2850 | \low[1,1]{5d}{big} - 2851 | \low[2,2]{2b}{low} 2852 | }{short} 2853 | }{negative} 2854 | \end{gather*} 2855 | By interchanging the \val{sign} and \val{symbol} algorithm in the previous example, then the \val{symbol} algorithm will be applied first and the \val{sign} algorithm handles the symbolic ties. 2856 | \begin{gather*} 2857 | \pdv[sort-method = {symbol,sign,abs}, order={3a-3hh-2b, 4c+4gg+2ff, -5d-5ee}]{f}{x,y,z} \\ 2858 | \low{ 2859 | \low{ 2860 | \low{4gg}{big} + 2861 | \low[2,2]{2ff}{low} 2862 | }{positive} - 2863 | \low{ 2864 | \low[3,3]{5ee}{big} - 2865 | \low[2,2]{3hh}{low} 2866 | }{negative} 2867 | }{long} + 2868 | \low{ 2869 | \low{ 2870 | \low[1,2]{4c}{big} + 2871 | \low[1,1]{3a}{low} 2872 | }{positive} - 2873 | \low{ 2874 | \low[1,1]{5d}{big} - 2875 | \low[2,2]{2b}{low} 2876 | }{negative} 2877 | }{short} 2878 | \end{gather*} 2879 | 2880 | In contrast to the previous two examples with three algorithms, this example uses a sorting method with two algorithms: \keyval*{sort-method}{sign,symbol}. The terms are first sorted by sign and then by symbolic length. 2881 | \begin{gather*} 2882 | \pdv[sort-method = {sign,symbol}, order={3a-3hh-2b, 4c+4gg+2ff, -5d-5ee}]{f}{x,y,z} \\ 2883 | \low{ 2884 | \low{ 4gg + 2ff }{long} + 2885 | \low{ 3a + 4c }{short} 2886 | }{positive} - 2887 | \low{ 2888 | \low{ 3hh - 5ee }{long} - 2889 | \low{ 2b - 5d }{short} 2890 | }{negative} 2891 | \end{gather*} 2892 | In the last example, a sorting method with a single algorithm, \keyval{sort-method}{symbol}, is used. 2893 | \begin{gather*} 2894 | \pdv[sort-method = symbol, order={3a-3hh-2b, 4c+4gg+2ff, -5d-5ee}]{f}{x,y,z} \\ 2895 | \low{ - 3hh + 4gg + 2ff - 5ee }{long} + 2896 | \low{ 3a - 2b + 4c - 5d }{short} 2897 | \end{gather*} 2898 | 2899 | \subsection{Treating the numerical term} \label{ssec:sort-numerical} 2900 | After handling the symbolic part of the mixed order, we now turn our attention to the numerical term\footref{foot:numerical-term}, which has a symbolic length of zero. For this reason it is treated differently than the symbolic terms. It can be placed either at the beginning or at the end of the mixed order by \val{first} and \val{last}, respectively. Alternatively, it is automatically positioned in the mixed order using \val{auto}. Setting \keyval{sort-numerical}{symbolic}, treats the numerical term as a symbolic term. Its behaviour is determined by the chosen algorithms in \keyval*{sort-method}{\dots}. In this example the sort method is the default value of the package. 2901 | \begin{align*} 2902 | \text{\inlinecode{sort-numerical=auto:}} && 2903 | \pdv[order={\beta, 2}, sort-numerical=auto]{f}{x,y} && 2904 | \pdv[order={\beta, -2}, sort-numerical=auto]{f}{x,y} && 2905 | \pdv[order={-\beta, 2}, sort-numerical=auto]{f}{x,y} && 2906 | \pdv[order={-\beta, -2}, sort-numerical=auto]{f}{x,y} \\ 2907 | \text{\inlinecode{sort-numerical=first:}} && 2908 | \pdv[order={\beta, 2}, sort-numerical=first]{f}{x,y} && \pdv[order={\beta, -2}, sort-numerical=first]{f}{x,y} && \pdv[order={-\beta, 2}, sort-numerical=first]{f}{x,y} && \pdv[order={-\beta, -2}, sort-numerical=first]{f}{x,y} \\ 2909 | \text{\inlinecode{sort-numerical=last:}} && 2910 | \pdv[order={\beta, 2}, sort-numerical=last]{f}{x,y} && \pdv[order={\beta, -2}, sort-numerical=last]{f}{x,y} && \pdv[order={-\beta, 2}, sort-numerical=last]{f}{x,y} && \pdv[order={-\beta, -2}, sort-numerical=last]{f}{x,y} \\ 2911 | \text{\inlinecode{sort-numerical=symbolic:}} && 2912 | \pdv[order={\beta, 2}, sort-numerical=symbolic]{f}{x,y} && \pdv[order={\beta, -2}, sort-numerical=symbolic]{f}{x,y} && \pdv[order={-\beta, 2}, sort-numerical=symbolic]{f}{x,y} && \pdv[order={-\beta, -2}, sort-numerical=symbolic]{f}{x,y} 2913 | \end{align*} 2914 | 2915 | \subsection{Reversing the sort algorithm} \label{ssec:sort-reverse} 2916 | The reverse keys serves to reverse the sorting algorithms' ordering, providing more flexibility over the sorting method. If the default ordering of an algorithm is not preferred it may be reversed with the corresponding reverse key. The examples below showcase the reverse functionality. Note that \keyval*[index=false]{sort-method}{1 algorithm only} is also used to better demonstrate the reverse feature, where the algorithm is the one used in the reverse key. 2917 | \begin{align*} 2918 | \text{\inlinecode{sort-abs-reverse=false:}} && \pdv[sort-method={abs}, sort-abs-reverse=false, order={2a, -3b}]{f}{x,y} && 2919 | \text{\inlinecode{sort-abs-reverse=true:}} && \pdv[sort-method={abs}, sort-abs-reverse=true, order={2a, -3b}]{f}{x,y} \\ 2920 | \text{\inlinecode{sort-number-reverse=false:}} && \pdv[sort-method={number}, sort-number-reverse=false, order={2a, -3b}]{f}{x,y} && 2921 | \text{\inlinecode{sort-number-reverse=true:}} && \pdv[sort-method={number}, sort-number-reverse=true, order={2a, -3b}]{f}{x,y} \\ 2922 | \text{\inlinecode{sort-sign-reverse=false:}} && \pdv[sort-method={sign}, sort-sign-reverse=false, order={a, -b}]{f}{x,y} && 2923 | \text{\inlinecode{sort-sign-reverse=true:}} && \pdv[sort-method={sign}, sort-sign-reverse=true, order={a, -b}]{f}{x,y} \\ 2924 | \text{\inlinecode{sort-symbol-reverse=false:}} && \pdv[sort-method={symbol}, sort-symbol-reverse=false, order={ab, c}]{f}{x,y} && 2925 | \text{\inlinecode{sort-symbol-reverse=true:}} && \pdv[sort-method={symbol}, sort-symbol-reverse=true, order={ab, c}]{f}{x,y} \\ 2926 | \text{\inlinecode{sort-lexical-reverse=false:}} && \pdv[sort-method={lexical}, sort-lexical-reverse=false, order={a, c, b}]{f}{x,y,z} && 2927 | \text{\inlinecode{sort-lexical-reverse=true:}} && \pdv[sort-method={lexical}, sort-lexical-reverse=true, order={a, c, b}]{f}{x,y,z} \\ 2928 | \end{align*} 2929 | 2930 | %\subsection{Mixed order override} 2931 | %In cases where the mixed order fails to be calculated or another form is preferred, then the mixed order override can be used 2932 | %\begin{example} 2933 | % \pdv[order={n+3k, n-k}]{f}{x,y} \\ 2934 | % \pdv[order={n+3k, n-k}, mixed-order={2(n+k)}]{f}{x,y} 2935 | %\end{example} 2936 | 2937 | 2938 | 2939 | \clearpage 2940 | \section{Miscellaneous} 2941 | 2942 | \subsection{Slashfrac}\label{ssec:slashfrac} 2943 | \begin{function}*{\slashfrac} 2944 | \begin{syntax} 2945 | \oarg{scale}, \marg{numerator}, \marg{denominator} 2946 | \end{syntax} 2947 | The text-styled fraction, $\slashfrac{a}{b}$, is commonly used in text-mode. While \macro{\slashfrac}[\narg{a},\narg{b}] requires more keystrokes to write than \texttt{a/b}, a macro is needed for implementing text-styled derivatives. 2948 | 2949 | \begin{argument}{1} 2950 | The optional argument serves as the scaling parameter for the solidus and accepts the following inputs: 2951 | \begin{example} 2952 | \slashfrac{y_f}{x} \\ 2953 | \slashfrac[auto]{y_f}{x} \\ 2954 | \slashfrac[none]{y_f}{x} \\ 2955 | \slashfrac[big]{y_f}{x} \\ 2956 | \slashfrac[Big]{y_f}{x} \\ 2957 | \slashfrac[bigg]{y_f}{x} \\ 2958 | \slashfrac[Bigg]{y_f}{x} 2959 | \end{example} 2960 | Omitting \arg{1} sets the scaling parameter to \val{auto}. 2961 | %This argument is subject to change, see \cref{consid:slashfrac_opt} for more information. 2962 | \end{argument} 2963 | 2964 | \begin{argument}{2} 2965 | Typesets the fraction's numerator. 2966 | \end{argument} 2967 | 2968 | \begin{argument}{3} 2969 | Typesets the fraction's denominator. 2970 | \end{argument} 2971 | \end{function} 2972 | 2973 | 2974 | \clearpage 2975 | \addsec{Index} 2976 | Numbers in bold refer to the page where the entry is defined. 2977 | 2978 | \printindex[option] 2979 | 2980 | \clearpage 2981 | 2982 | \printindex[macro] 2983 | 2984 | \clearpage 2985 | \addsec{Change history} 2986 | 2987 | \setlength{\marginparwidth}{75pt} 2988 | 2989 | \begin{changelog} 2990 | \begin{change}[version=0.9, date=2019-07-21, beta=true] 2991 | \item First release of the package. The package is currently in a beta version. 2992 | \end{change} 2993 | \bigskip 2994 | \begin{change}[version=0.95, date=2019-09-18, beta=true] 2995 | \item \emph{Please ignore this version, since it contained the wrong \pkg{.sty} and \pkg{.pdf} files} \texttt{:(}. 2996 | %\item Second beta release of the package. 2997 | \item Removed the single token restriction on the infinitesimal since it was unnecessary. 2998 | \item Fixed documentation errors and typos. 2999 | \item Made minor fixes to the code. 3000 | \end{change} 3001 | \begin{change}[version=0.95b, date=2019-09-21, beta=true] 3002 | \item Contains the correct \pkg{.sty} and \pkg{.pdf} files \texttt{:)}. 3003 | \item Made one minor code fix. 3004 | \end{change} 3005 | \smallskip 3006 | \begin{change}[version=0.96, date=2019-12-22, beta=true] 3007 | \item Fixed the issue with double superscript for higher-order derivatives when the variable contained a superscript. 3008 | \end{change} 3009 | \smallskip 3010 | \begin{change}[version=0.97, date=2020-02-03, beta=true] 3011 | \item Fixed the argument specifier of \csverb{\__deriv_scale_big:nnnn} when it was used (it was used with \texttt{:nnnm}). 3012 | \end{change} 3013 | \smallskip 3014 | \begin{change}[version=0.98, date=2020-07-20, beta=true] 3015 | \item Fixed a bug related to the subscript argument caused by recent changes to the \pkg{xparse} package dated 2020-05-14 (the fix also works with earlier versions of \pkg{xparse}). 3016 | \end{change} 3017 | \smallskip 3018 | \begin{change}[version=1.0, date=2021-05-25, beta=false] 3019 | \item Added new options for derivatives. 3020 | \item Added new values for existing options. 3021 | \item Added new commands for writing differentials. 3022 | \item Changed the usage of \key[index=false]{style-inf}. 3023 | \item Changed the order argument to an option argument. 3024 | \item Adjusted default values for certain options. 3025 | \item Expanded math space keys to accept more general inputs. 3026 | \item Changed \cs{derivset} to define default options. 3027 | \item Merged the codes for ordinary and partial derivatives. 3028 | \item Removed the mixed order argument. 3029 | \item Removed the options \key[index=false]{misc-add-delims} and \key[index=false]{misc-remove-delims}. 3030 | \item Replaced the commands in \cref{sec:defvar} with new ones, as the old ones are deprecated. 3031 | \item Code clean-up and optimization. 3032 | \item Fixed code errors. 3033 | \item Fixed documentation errors. 3034 | \item Improved support for preventing options affecting nested derivatives/differentials. 3035 | \end{change} 3036 | \begin{change}[version=1.01, date=2021-05-28, beta=false] 3037 | \item Changed the default value of the option \key[index=false]{sep-end} due to issues. 3038 | \item Fixed code errors due to changes introduced in version 1.0 to the option \key[index=false]{style-inf}. 3039 | \item Fixed documentation errors. 3040 | \end{change} 3041 | \begin{change}[version=1.1, date=2021-06-03, beta=false] 3042 | \item Added package options to be used with \cs{usepackage}\oarg{options}\narg{derivative}. 3043 | \item Removed the hidden dependency on \pkg{unicode-math} when using \xetex{} or \luatex. 3044 | \item Replaced \cs{symup} with \cs{mathrm} for simplicity. 3045 | \item If \pkg{mleftright} is loaded, the default value of \key[index=false]{scale-auto} is set to \val{mleftmright}. 3046 | \end{change} 3047 | \begin{change}[version=1.2, date=2022-07-09, beta=false] 3048 | \item Code clean-up and optimisation that significantly speeds up usage of the package. 3049 | \item Added new a sorting algorithm \keyval[index=false]{sort-method}{lexical}, which sorts terms alphabetically. 3050 | \item Added the option \key[index=false]{sort-lexical-reverse} to reverse the alphabetical sorting order. 3051 | \item Added the option \key[index=false]{switch-sort} to enable/disable the sorting algorithm for the mixed order. 3052 | \item Fixed a bug related to \keyval[index=false]{scale-\meta{\dots}}{none} when the corresponding delimiter option contained a period. 3053 | \item Fixed documentation errors. 3054 | \end{change} 3055 | \begin{change}[version=1.3, date=2023-07-26, beta=false] 3056 | \item Code clean-up and minor optimisation. 3057 | \item Fixed documentation errors. 3058 | \item Updated documentation to include more examples. 3059 | \item Enhanced the algorithm that automatically calculates the mixed order to support fractional calculus. 3060 | \item Introduced a new argument, \targ{!}, for derivatives to enable shorthand notation. 3061 | \item Added new options \key[index=false]{style-inf-den}. 3062 | and \key[index=false]{style-inf-num} to set the infinitesimals in the denominator and numerator, respectively. 3063 | \item Added new options \key{style-var-/}, \key{style-var-!} and \key{style-var-/!} to set the style of the derivatives. 3064 | \item Added new options \key{scale-var-!} and \key{delims-var-!} for variable delimiters in shorthand mode. 3065 | \item Added new options \key{scale-eval-!} and \key{delims-eval-!} for evaluation delimiters in shorthand mode. 3066 | \end{change} 3067 | \begin{change}[version=1.31, date=2023-11-04, beta=false] 3068 | \item Fixed issue relating to the order when nesting derivatives (issues \#14). 3069 | \end{change} 3070 | \bigskip 3071 | \begin{change}[version=1.4, date=2024-02-08, beta=false] 3072 | \item Introduced implicit order parameter to simplify specifying the order of differentiation, for example: \cs{pdv}\oarg*{n,2}\narg{f}\narg{x,y} (issues \#2 and \#10). 3073 | \end{change} 3074 | \end{changelog} 3075 | 3076 | 3077 | \end{document} --------------------------------------------------------------------------------