diff options
Diffstat (limited to 'doc/source')
-rw-r--r-- | doc/source/dev/alignment.rst | 96 | ||||
-rw-r--r-- | doc/source/dev/conduct/code_of_conduct.rst | 163 | ||||
-rw-r--r-- | doc/source/dev/conduct/report_handling_manual.rst | 218 | ||||
-rw-r--r-- | doc/source/dev/index.rst | 1 | ||||
-rw-r--r-- | doc/source/f2py/compile_session.dat | 4 | ||||
-rw-r--r-- | doc/source/f2py/getting-started.rst | 10 | ||||
-rw-r--r-- | doc/source/f2py/run_main_session.dat | 12 | ||||
-rw-r--r-- | doc/source/f2py/usage.rst | 24 | ||||
-rw-r--r-- | doc/source/reference/arrays.dtypes.rst | 7 | ||||
-rw-r--r-- | doc/source/reference/c-api.array.rst | 8 | ||||
-rw-r--r-- | doc/source/reference/c-api.generalized-ufuncs.rst | 8 | ||||
-rw-r--r-- | doc/source/reference/c-api.types-and-structures.rst | 63 | ||||
-rw-r--r-- | doc/source/reference/c-api.ufunc.rst | 75 | ||||
-rw-r--r-- | doc/source/reference/internals.code-explanations.rst | 8 | ||||
-rw-r--r-- | doc/source/reference/routines.polynomials.classes.rst | 15 | ||||
-rw-r--r-- | doc/source/release.rst | 3 | ||||
-rw-r--r-- | doc/source/user/c-info.beyond-basics.rst | 32 | ||||
-rw-r--r-- | doc/source/user/c-info.python-as-glue.rst | 38 | ||||
-rw-r--r-- | doc/source/user/c-info.ufunc-tutorial.rst | 131 |
19 files changed, 688 insertions, 228 deletions
diff --git a/doc/source/dev/alignment.rst b/doc/source/dev/alignment.rst new file mode 100644 index 000000000..f067f0d03 --- /dev/null +++ b/doc/source/dev/alignment.rst @@ -0,0 +1,96 @@ +.. _alignment: + + +Numpy Alignment Goals +===================== + +There are three use-cases related to memory alignment in numpy (as of 1.14): + + 1. Creating structured datatypes with fields aligned like in a C-struct. + 2. Speeding up copy operations by using uint assignment in instead of memcpy + 3. Guaranteeing safe aligned access for ufuncs/setitem/casting code + +Numpy uses two different forms of alignment to achieve these goals: +"True alignment" and "Uint alignment". + +"True" alignment refers to the architecture-dependent alignment of an +equivalent C-type in C. For example, in x64 systems ``numpy.float64`` is +equivalent to ``double`` in C. On most systems this has either an alignment of +4 or 8 bytes (and this can be controlled in gcc by the option +``malign-double``). A variable is aligned in memory if its memory offset is a +multiple of its alignment. On some systems (eg sparc) memory alignment is +required, on others it gives a speedup. + +"Uint" alignment depends on the size of a datatype. It is defined to be the +"True alignment" of the uint used by numpy's copy-code to copy the datatype, or +undefined/unaligned if there is no equivalent uint. Currently numpy uses uint8, +uint16, uint32, uint64 and uint64 to copy data of size 1,2,4,8,16 bytes +respectively, and all other sized datatypes cannot be uint-aligned. + +For example, on a (typical linux x64 gcc) system, the numpy ``complex64`` +datatype is implemented as ``struct { float real, imag; }``. This has "true" +alignment of 4 and "uint" alignment of 8 (equal to the true alignment of +``uint64``). + +Variables in Numpy which control and describe alignment +======================================================= + +There are 4 relevant uses of the word ``align`` used in numpy: + + * The ``dtype.alignment`` attribute (``descr->alignment`` in C). This is meant + to reflect the "true alignment" of the type. It has arch-dependent default + values for all datatypes, with the exception of structured types created + with ``align=True`` as described below. + * The ``ALIGNED`` flag of an ndarray, computed in ``IsAligned`` and checked + by ``PyArray_ISALIGNED``. This is computed from ``dtype.alignment``. + It is set to ``True`` if every item in the array is at a memory location + consistent with ``dtype.alignment``, which is the case if the data ptr and + all strides of the array are multiples of that alignment. + * The ``align`` keyword of the dtype constructor, which only affects structured + arrays. If the structure's field offsets are not manually provided numpy + determines offsets automatically. In that case, ``align=True`` pads the + structure so that each field is "true" aligned in memory and sets + ``dtype.alignment`` to be the largest of the field "true" alignments. This + is like what C-structs usually do. Otherwise if offsets or itemsize were + manually provided ``align=True`` simply checks that all the fields are + "true" aligned and that the total itemsize is a multiple of the largest + field alignment. In either case ``dtype.isalignedstruct`` is also set to + True. + * ``IsUintAligned`` is used to determine if an ndarray is "uint aligned" in + an analagous way to how ``IsAligned`` checks for true-alignment. + +Consequences of alignment +========================= + +Here is how the variables above are used: + + 1. Creating aligned structs: In order to know how to offset a field when + ``align=True``, numpy looks up ``field.dtype.alignment``. This includes + fields which are nested structured arrays. + 2. Ufuncs: If the ``ALIGNED`` flag of an array is False, ufuncs will + buffer/cast the array before evaluation. This is needed since ufunc inner + loops access raw elements directly, which might fail on some archs if the + elements are not true-aligned. + 3. Getitem/setitem/copyswap function: Similar to ufuncs, these functions + generally have two code paths. If ``ALIGNED`` is False they will + use a code path that buffers the arguments so they are true-aligned. + 4. Strided copy code: Here, "uint alignment" is used instead. If the itemsize + of an array is equal to 1, 2, 4, 8 or 16 bytes and the array is uint + aligned then instead numpy will do ``*(uintN*)dst) = *(uintN*)src)`` for + appropriate N. Otherwise numpy copies by doing ``memcpy(dst, src, N)``. + 5. Nditer code: Since this often calls the strided copy code, it must + check for "uint alignment". + 6. Cast code: if the array is "uint aligned" this will essentially do + ``*dst = CASTFUNC(*src)``. If not, it does + ``memmove(srcval, src); dstval = CASTFUNC(srcval); memmove(dst, dstval)`` + where dstval/srcval are aligned. + +Note that in principle, only "true alignment" is required for casting code. +However, because the casting code and copy code are deeply intertwined they +both use "uint" alignment. This should be safe assuming uint alignment is +always larger than true alignment, though it can cause unnecessary buffering if +an array is "true aligned" but not "uint aligned". If there is ever a big +rewrite of this code it would be good to allow them to use different +alignments. + + diff --git a/doc/source/dev/conduct/code_of_conduct.rst b/doc/source/dev/conduct/code_of_conduct.rst new file mode 100644 index 000000000..aca39d8a7 --- /dev/null +++ b/doc/source/dev/conduct/code_of_conduct.rst @@ -0,0 +1,163 @@ +NumPy Code of Conduct +===================== + + +Introduction +------------ + +This code of conduct applies to all spaces managed by the NumPy project, +including all public and private mailing lists, issue trackers, wikis, blogs, +Twitter, and any other communication channel used by our community. The NumPy +project does not organise in-person events, however events related to our +community should have a code of conduct similar in spirit to this one. + +This code of conduct should be honored by everyone who participates in +the NumPy community formally or informally, or claims any affiliation with the +project, in any project-related activities and especially when representing the +project, in any role. + +This code is not exhaustive or complete. It serves to distill our common +understanding of a collaborative, shared environment and goals. Please try to +follow this code in spirit as much as in letter, to create a friendly and +productive environment that enriches the surrounding community. + + +Specific Guidelines +------------------- + +We strive to: + +1. Be open. We invite anyone to participate in our community. We prefer to use + public methods of communication for project-related messages, unless + discussing something sensitive. This applies to messages for help or + project-related support, too; not only is a public support request much more + likely to result in an answer to a question, it also ensures that any + inadvertent mistakes in answering are more easily detected and corrected. + +2. Be empathetic, welcoming, friendly, and patient. We work together to resolve + conflict, and assume good intentions. We may all experience some frustration + from time to time, but we do not allow frustration to turn into a personal + attack. A community where people feel uncomfortable or threatened is not a + productive one. + +3. Be collaborative. Our work will be used by other people, and in turn we will + depend on the work of others. When we make something for the benefit of the + project, we are willing to explain to others how it works, so that they can + build on the work to make it even better. Any decision we make will affect + users and colleagues, and we take those consequences seriously when making + decisions. + +4. Be inquisitive. Nobody knows everything! Asking questions early avoids many + problems later, so we encourage questions, although we may direct them to + the appropriate forum. We will try hard to be responsive and helpful. + +5. Be careful in the words that we choose. We are careful and respectful in + our communication and we take responsibility for our own speech. Be kind to + others. Do not insult or put down other participants. We will not accept + harassment or other exclusionary behaviour, such as: + + - Violent threats or language directed against another person. + - Sexist, racist, or otherwise discriminatory jokes and language. + - Posting sexually explicit or violent material. + - Posting (or threatening to post) other people's personally identifying information ("doxing"). + - Sharing private content, such as emails sent privately or non-publicly, + or unlogged forums such as IRC channel history, without the sender's consent. + - Personal insults, especially those using racist or sexist terms. + - Unwelcome sexual attention. + - Excessive profanity. Please avoid swearwords; people differ greatly in their sensitivity to swearing. + - Repeated harassment of others. In general, if someone asks you to stop, then stop. + - Advocating for, or encouraging, any of the above behaviour. + + +Diversity Statement +------------------- + +The NumPy project welcomes and encourages participation by everyone. We are +committed to being a community that everyone enjoys being part of. Although +we may not always be able to accommodate each individual's preferences, we try +our best to treat everyone kindly. + +No matter how you identify yourself or how others perceive you: we welcome you. +Though no list can hope to be comprehensive, we explicitly honour diversity in: +age, culture, ethnicity, genotype, gender identity or expression, language, +national origin, neurotype, phenotype, political beliefs, profession, race, +religion, sexual orientation, socioeconomic status, subculture and technical +ability, to the extent that these do not conflict with this code of conduct. + + +Though we welcome people fluent in all languages, NumPy development is +conducted in English. + +Standards for behaviour in the NumPy community are detailed in the Code of +Conduct above. Participants in our community should uphold these standards +in all their interactions and help others to do so as well (see next section). + + +Reporting Guidelines +-------------------- + +We know that it is painfully common for internet communication to start at or +devolve into obvious and flagrant abuse. We also recognize that sometimes +people may have a bad day, or be unaware of some of the guidelines in this Code +of Conduct. Please keep this in mind when deciding on how to respond to a +breach of this Code. + +For clearly intentional breaches, report those to the Code of Conduct committee +(see below). For possibly unintentional breaches, you may reply to the person +and point out this code of conduct (either in public or in private, whatever is +most appropriate). If you would prefer not to do that, please feel free to +report to the Code of Conduct Committee directly, or ask the Committee for +advice, in confidence. + +You can report issues to the NumPy Code of Conduct committee, at +numpy-conduct@googlegroups.com. Currently, the committee consists of: + +- Stefan van der Walt +- Nathaniel J. Smith +- Ralf Gommers + +If your report involves any members of the committee, or if they feel they have +a conflict of interest in handling it, then they will recuse themselves from +considering your report. Alternatively, if for any reason you feel +uncomfortable making a report to the committee, then you can also contact: + +- Senior `NumFOCUS staff <https://numfocus.org/code-of-conduct#persons-responsible>`__: conduct@numfocus.org + + +Incident reporting resolution & Code of Conduct enforcement +----------------------------------------------------------- + +*This section summarizes the most important points, more details can be found +in* :ref:`CoC_reporting_manual`. + +We will investigate and respond to all complaints. The NumPy Code of Conduct +Committee and the NumPy Steering Committee (if involved) will protect the +identity of the reporter, and treat the content of complaints as confidential +(unless the reporter agrees otherwise). + +In case of severe and obvious breaches, e.g. personal threat or violent, sexist +or racist language, we will immediately disconnect the originator from NumPy +communication channels; please see the manual for details. + +In cases not involving clear severe and obvious breaches of this code of +conduct, the process for acting on any received code of conduct violation +report will be: + +1. acknowledge report is received +2. reasonable discussion/feedback +3. mediation (if feedback didn't help, and only if both reporter and reportee agree to this) +4. enforcement via transparent decision (see :ref:`CoC_resolutions`) by the + Code of Conduct Committee + +The committee will respond to any report as soon as possible, and at most +within 72 hours. + + +Endnotes +-------- + +We are thankful to the groups behind the following documents, from which we +drew content and inspiration: + +- `The SciPy Code of Conduct <https://docs.scipy.org/doc/scipy/reference/dev/conduct/code_of_conduct.html>`_ + diff --git a/doc/source/dev/conduct/report_handling_manual.rst b/doc/source/dev/conduct/report_handling_manual.rst new file mode 100644 index 000000000..5f5e32f13 --- /dev/null +++ b/doc/source/dev/conduct/report_handling_manual.rst @@ -0,0 +1,218 @@ +.. _CoC_reporting_manual: + +NumPy Code of Conduct - How to follow up on a report +---------------------------------------------------- + +This is the manual followed by NumPy's Code of Conduct Committee. It's used +when we respond to an issue to make sure we're consistent and fair. + +Enforcing the Code of Conduct impacts our community today and for the future. +It's an action that we do not take lightly. When reviewing enforcement +measures, the Code of Conduct Committee will keep the following values and +guidelines in mind: + +* Act in a personal manner rather than impersonal. The Committee can engage + the parties to understand the situation, while respecting the privacy and any + necessary confidentiality of reporters. However, sometimes it is necessary + to communicate with one or more individuals directly: the Committee's goal is + to improve the health of our community rather than only produce a formal + decision. + +* Emphasize empathy for individuals rather than judging behavior, avoiding + binary labels of "good" and "bad/evil". Overt, clear-cut aggression and + harassment exists and we will be address that firmly. But many scenarios + that can prove challenging to resolve are those where normal disagreements + devolve into unhelpful or harmful behavior from multiple parties. + Understanding the full context and finding a path that re-engages all is + hard, but ultimately the most productive for our community. + +* We understand that email is a difficult medium and can be isolating. + Receiving criticism over email, without personal contact, can be + particularly painful. This makes it especially important to keep an + atmosphere of open-minded respect of the views of others. It also means + that we must be transparent in our actions, and that we will do everything + in our power to make sure that all our members are treated fairly and with + sympathy. + +* Discrimination can be subtle and it can be unconscious. It can show itself + as unfairness and hostility in otherwise ordinary interactions. We know + that this does occur, and we will take care to look out for it. We would + very much like to hear from you if you feel you have been treated unfairly, + and we will use these procedures to make sure that your complaint is heard + and addressed. + +* Help increase engagement in good discussion practice: try to identify where + discussion may have broken down and provide actionable information, pointers + and resources that can lead to positive change on these points. + +* Be mindful of the needs of new members: provide them with explicit support + and consideration, with the aim of increasing participation from + underrepresented groups in particular. + +* Individuals come from different cultural backgrounds and native languages. + Try to identify any honest misunderstandings caused by a non-native speaker + and help them understand the issue and what they can change to avoid causing + offence. Complex discussion in a foreign language can be very intimidating, + and we want to grow our diversity also across nationalities and cultures. + +*Mediation*: voluntary, informal mediation is a tool at our disposal. In +contexts such as when two or more parties have all escalated to the point of +inappropriate behavior (something sadly common in human conflict), it may be +useful to facilitate a mediation process. This is only an example: the +Committee can consider mediation in any case, mindful that the process is meant +to be strictly voluntary and no party can be pressured to participate. If the +Committee suggests mediation, it should: + +* Find a candidate who can serve as a mediator. +* Obtain the agreement of the reporter(s). The reporter(s) have complete + freedom to decline the mediation idea, or to propose an alternate mediator. +* Obtain the agreement of the reported person(s). +* Settle on the mediator: while parties can propose a different mediator than + the suggested candidate, only if common agreement is reached on all terms can + the process move forward. +* Establish a timeline for mediation to complete, ideally within two weeks. + +The mediator will engage with all the parties and seek a resolution that is +satisfactory to all. Upon completion, the mediator will provide a report +(vetted by all parties to the process) to the Committee, with recommendations +on further steps. The Committee will then evaluate these results (whether +satisfactory resolution was achieved or not) and decide on any additional +action deemed necessary. + + +How the committee will respond to reports +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When the committee (or a committee member) receives a report, they will first +determine whether the report is about a clear and severe breach (as defined +below). If so, immediate action needs to be taken in addition to the regular +report handling process. + +Clear and severe breach actions ++++++++++++++++++++++++++++++++ + +We know that it is painfully common for internet communication to start at or +devolve into obvious and flagrant abuse. We will deal quickly with clear and +severe breaches like personal threats, violent, sexist or racist language. + +When a member of the Code of Conduct committee becomes aware of a clear and +severe breach, they will do the following: + +* Immediately disconnect the originator from all NumPy communication channels. +* Reply to the reporter that their report has been received and that the + originator has been disconnected. +* In every case, the moderator should make a reasonable effort to contact the + originator, and tell them specifically how their language or actions + qualify as a "clear and severe breach". The moderator should also say + that, if the originator believes this is unfair or they want to be + reconnected to NumPy, they have the right to ask for a review, as below, by + the Code of Conduct Committee. + The moderator should copy this explanation to the Code of Conduct Committee. +* The Code of Conduct Committee will formally review and sign off on all cases + where this mechanism has been applied to make sure it is not being used to + control ordinary heated disagreement. + +Report handling ++++++++++++++++ + +When a report is sent to the committee they will immediately reply to the +reporter to confirm receipt. This reply must be sent within 72 hours, and the +group should strive to respond much quicker than that. + +If a report doesn't contain enough information, the committee will obtain all +relevant data before acting. The committee is empowered to act on the Steering +Council’s behalf in contacting any individuals involved to get a more complete +account of events. + +The committee will then review the incident and determine, to the best of their +ability: + +* What happened. +* Whether this event constitutes a Code of Conduct violation. +* Who are the responsible party(ies). +* Whether this is an ongoing situation, and there is a threat to anyone's + physical safety. + +This information will be collected in writing, and whenever possible the +group's deliberations will be recorded and retained (i.e. chat transcripts, +email discussions, recorded conference calls, summaries of voice conversations, +etc). + +It is important to retain an archive of all activities of this committee to +ensure consistency in behavior and provide institutional memory for the +project. To assist in this, the default channel of discussion for this +committee will be a private mailing list accessible to current and future +members of the committee as well as members of the Steering Council upon +justified request. If the Committee finds the need to use off-list +communications (e.g. phone calls for early/rapid response), it should in all +cases summarize these back to the list so there's a good record of the process. + +The Code of Conduct Committee should aim to have a resolution agreed upon within +two weeks. In the event that a resolution can't be determined in that time, the +committee will respond to the reporter(s) with an update and projected timeline +for resolution. + + +.. _CoC_resolutions: + +Resolutions +~~~~~~~~~~~ + +The committee must agree on a resolution by consensus. If the group cannot reach +consensus and deadlocks for over a week, the group will turn the matter over to +the Steering Council for resolution. + + +Possible responses may include: + +* Taking no further action + + - if we determine no violations have occurred. + - if the matter has been resolved publicly while the committee was considering responses. + +* Coordinating voluntary mediation: if all involved parties agree, the + Committee may facilitate a mediation process as detailed above. +* Remind publicly, and point out that some behavior/actions/language have been + judged inappropriate and why in the current context, or can but hurtful to + some people, requesting the community to self-adjust. +* A private reprimand from the committee to the individual(s) involved. In this + case, the group chair will deliver that reprimand to the individual(s) over + email, cc'ing the group. +* A public reprimand. In this case, the committee chair will deliver that + reprimand in the same venue that the violation occurred, within the limits of + practicality. E.g., the original mailing list for an email violation, but + for a chat room discussion where the person/context may be gone, they can be + reached by other means. The group may choose to publish this message + elsewhere for documentation purposes. +* A request for a public or private apology, assuming the reporter agrees to + this idea: they may at their discretion refuse further contact with the + violator. The chair will deliver this request. The committee may, if it + chooses, attach "strings" to this request: for example, the group may ask a + violator to apologize in order to retain one’s membership on a mailing list. +* A "mutually agreed upon hiatus" where the committee asks the individual to + temporarily refrain from community participation. If the individual chooses + not to take a temporary break voluntarily, the committee may issue a + "mandatory cooling off period". +* A permanent or temporary ban from some or all NumPy spaces (mailing lists, + gitter.im, etc.). The group will maintain records of all such bans so that + they may be reviewed in the future or otherwise maintained. + +Once a resolution is agreed upon, but before it is enacted, the committee will +contact the original reporter and any other affected parties and explain the +proposed resolution. The committee will ask if this resolution is acceptable, +and must note feedback for the record. + +Finally, the committee will make a report to the NumPy Steering Council (as +well as the NumPy core team in the event of an ongoing resolution, such as a +ban). + +The committee will never publicly discuss the issue; all public statements will +be made by the chair of the Code of Conduct Committee or the NumPy Steering +Council. + + +Conflicts of Interest +~~~~~~~~~~~~~~~~~~~~~ + +In the event of any conflict of interest, a committee member must immediately +notify the other members, and recuse themselves if necessary. diff --git a/doc/source/dev/index.rst b/doc/source/dev/index.rst index 04c84eb61..9ce04cc1b 100644 --- a/doc/source/dev/index.rst +++ b/doc/source/dev/index.rst @@ -5,6 +5,7 @@ Contributing to NumPy .. toctree:: :maxdepth: 3 + conduct/code_of_conduct gitwash/index development_environment releasing diff --git a/doc/source/f2py/compile_session.dat b/doc/source/f2py/compile_session.dat index 0d8408198..5c42742be 100644 --- a/doc/source/f2py/compile_session.dat +++ b/doc/source/f2py/compile_session.dat @@ -1,10 +1,10 @@ ->>> import f2py2e +>>> import numpy.f2py >>> fsource = ''' ... subroutine foo ... print*, "Hello world!" ... end ... ''' ->>> f2py2e.compile(fsource,modulename='hello',verbose=0) +>>> numpy.f2py.compile(fsource, modulename='hello', verbose=0) 0 >>> import hello >>> hello.foo() diff --git a/doc/source/f2py/getting-started.rst b/doc/source/f2py/getting-started.rst index fffd61c45..3d8ea24e4 100644 --- a/doc/source/f2py/getting-started.rst +++ b/doc/source/f2py/getting-started.rst @@ -45,9 +45,9 @@ to run :: - f2py -c fib1.f -m fib1 + python -m numpy.f2py -c fib1.f -m fib1 -This command builds (see ``-c`` flag, execute ``f2py`` without +This command builds (see ``-c`` flag, execute ``python -m numpy.f2py`` without arguments to see the explanation of command line options) an extension module ``fib1.so`` (see ``-m`` flag) to the current directory. Now, in Python the Fortran subroutine ``FIB`` is accessible via ``fib1.fib``:: @@ -162,7 +162,7 @@ one. :: - f2py fib1.f -m fib2 -h fib1.pyf + python -m numpy.f2py fib1.f -m fib2 -h fib1.pyf The signature file is saved to ``fib1.pyf`` (see ``-h`` flag) and its contents is shown below. @@ -188,7 +188,7 @@ one. :: - f2py -c fib2.pyf fib1.f + python -m numpy.f2py -c fib2.pyf fib1.f In Python:: @@ -243,7 +243,7 @@ __ fib3.f Building the extension module can be now carried out in one command:: - f2py -c -m fib3 fib3.f + python -m numpy.f2py -c -m fib3 fib3.f Notice that the resulting wrapper to ``FIB`` is as "smart" as in previous case:: diff --git a/doc/source/f2py/run_main_session.dat b/doc/source/f2py/run_main_session.dat index 29ecc3dfe..b9a7e1b0d 100644 --- a/doc/source/f2py/run_main_session.dat +++ b/doc/source/f2py/run_main_session.dat @@ -1,14 +1,14 @@ ->>> import f2py2e ->>> r=f2py2e.run_main(['-m','scalar','docs/usersguide/scalar.f']) +>>> import numpy.f2py +>>> r = numpy.f2py.run_main(['-m','scalar','doc/source/f2py/scalar.f']) Reading fortran codes... - Reading file 'docs/usersguide/scalar.f' + Reading file 'doc/source/f2py/scalar.f' (format:fix,strict) Post-processing... Block: scalar Block: FOO Building modules... Building module "scalar"... Wrote C/API module "scalar" to file "./scalarmodule.c" ->>> print r -{'scalar': {'h': ['/home/users/pearu/src_cvs/f2py2e/src/fortranobject.h'], +>>> printr(r) +{'scalar': {'h': ['/home/users/pearu/src_cvs/f2py/src/fortranobject.h'], 'csrc': ['./scalarmodule.c', - '/home/users/pearu/src_cvs/f2py2e/src/fortranobject.c']}} + '/home/users/pearu/src_cvs/f2py/src/fortranobject.c']}} diff --git a/doc/source/f2py/usage.rst b/doc/source/f2py/usage.rst index a6f093154..0f5068e0e 100644 --- a/doc/source/f2py/usage.rst +++ b/doc/source/f2py/usage.rst @@ -3,7 +3,19 @@ Using F2PY =========== F2PY can be used either as a command line tool ``f2py`` or as a Python -module ``f2py2e``. +module ``numpy.f2py``. While we try to install the command line tool as part +of the numpy setup, some platforms like Windows make it difficult to +reliably put the executable on the ``PATH``. We will refer to ``f2py`` +in this document but you may have to run it as a module + +``` +python -m numpy.f2py +``` + +If you run ``f2py`` with no arguments, and the line ``numpy Version`` at the +end matches the NumPy version printed from ``python -m numpy.f2py``, then you +can use the shorter version. If not, or if you cannot run ``f2py``, you should +replace all calls to ``f2py`` here with the longer version. Command ``f2py`` ================= @@ -194,15 +206,15 @@ Other options: Execute ``f2py`` without any options to get an up-to-date list of available options. -Python module ``f2py2e`` -========================= +Python module ``numpy.f2py`` +============================ .. warning:: - The current Python interface to ``f2py2e`` module is not mature and - may change in future depending on users needs. + The current Python interface to the ``f2py`` module is not mature and + may change in the future. -The following functions are provided by the ``f2py2e`` module: +The following functions are provided by the ``numpy.f2py`` module: ``run_main(<list>)`` Equivalent to running:: diff --git a/doc/source/reference/arrays.dtypes.rst b/doc/source/reference/arrays.dtypes.rst index d771f2940..f2072263f 100644 --- a/doc/source/reference/arrays.dtypes.rst +++ b/doc/source/reference/arrays.dtypes.rst @@ -391,8 +391,8 @@ Type strings When the optional keys *offsets* and *titles* are provided, their values must each be lists of the same length as the *names* and *formats* lists. The *offsets* value is a list of byte offsets - (integers) for each field, while the *titles* value is a list of - titles for each field (:const:`None` can be used if no title is + (limited to `ctypes.c_int`) for each field, while the *titles* value is a + list of titles for each field (:const:`None` can be used if no title is desired for that field). The *titles* can be any :class:`string` or :class:`unicode` object and will add another entry to the fields dictionary keyed by the title and referencing the same @@ -402,7 +402,8 @@ Type strings The *itemsize* key allows the total size of the dtype to be set, and must be an integer large enough so all the fields are within the dtype. If the dtype being constructed is aligned, - the *itemsize* must also be divisible by the struct alignment. + the *itemsize* must also be divisible by the struct alignment. Total dtype + *itemsize* is limited to `ctypes.c_int`. .. admonition:: Example diff --git a/doc/source/reference/c-api.array.rst b/doc/source/reference/c-api.array.rst index 5ea7bfcfc..9265b1a97 100644 --- a/doc/source/reference/c-api.array.rst +++ b/doc/source/reference/c-api.array.rst @@ -122,9 +122,11 @@ sub-types). .. c:function:: PyObject *PyArray_GETITEM(PyArrayObject* arr, void* itemptr) - Get a Python object from the ndarray, *arr*, at the location - pointed to by itemptr. Return ``NULL`` on failure. - + Get a Python object of a builtin type from the ndarray, *arr*, + at the location pointed to by itemptr. Return ``NULL`` on failure. + + `numpy.ndarray.item` is identical to PyArray_GETITEM. + .. c:function:: int PyArray_SETITEM( \ PyArrayObject* arr, void* itemptr, PyObject* obj) diff --git a/doc/source/reference/c-api.generalized-ufuncs.rst b/doc/source/reference/c-api.generalized-ufuncs.rst index dd8cf6558..2c631531f 100644 --- a/doc/source/reference/c-api.generalized-ufuncs.rst +++ b/doc/source/reference/c-api.generalized-ufuncs.rst @@ -145,11 +145,15 @@ Here are some examples of signatures: +-------------+------------------------+-----------------------------------+ | add | ``(),()->()`` | | +-------------+------------------------+-----------------------------------+ +| sum1d | ``(i)->()`` | | ++-------------+------------------------+-----------------------------------+ | inner1d | ``(i),(i)->()`` | | +-------------+------------------------+-----------------------------------+ -| sum1d | ``(i)->()`` | | +| matmat | ``(m,n),(n,p)->(m,p)`` | matrix multiplication | ++-------------+------------------------+-----------------------------------+ +| vecmat | ``(n),(n,p)->(p)`` | vector-matrix multiplication | +-------------+------------------------+-----------------------------------+ -| dot2d | ``(m,n),(n,p)->(m,p)`` | matrix multiplication | +| matvec | ``(m,n),(n)->(m)`` | matrix-vector multiplication | +-------------+------------------------+-----------------------------------+ | outer_inner | ``(i,t),(j,t)->(i,j)`` | inner over the last dimension, | | | | outer over the second to last, | diff --git a/doc/source/reference/c-api.types-and-structures.rst b/doc/source/reference/c-api.types-and-structures.rst index dcebd1ede..095693c5b 100644 --- a/doc/source/reference/c-api.types-and-structures.rst +++ b/doc/source/reference/c-api.types-and-structures.rst @@ -133,9 +133,9 @@ PyArray_Type is related to this array. There are two use cases: 1) If this array does not own its own memory, then base points to the Python object that owns it (perhaps another array object), 2) If this array has - the (deprecated) :c:data:`NPY_ARRAY_UPDATEIFCOPY` or + the (deprecated) :c:data:`NPY_ARRAY_UPDATEIFCOPY` or :c:data:NPY_ARRAY_WRITEBACKIFCOPY`: flag set, then this array is - a working copy of a "misbehaved" array. When + a working copy of a "misbehaved" array. When ``PyArray_ResolveWritebackIfCopy`` is called, the array pointed to by base will be updated with the contents of this array. @@ -683,7 +683,9 @@ PyUFunc_Type The core of the ufunc is the :c:type:`PyUFuncObject` which contains all the information needed to call the underlying C-code loops that - perform the actual work. It has the following structure: + perform the actual work. While it is described here for completeness, it + should be considered internal to NumPy and manipulated via ``PyUFunc_*`` + functions. It has the following structure: .. code-block:: c @@ -703,6 +705,16 @@ PyUFunc_Type void *ptr; PyObject *obj; PyObject *userloops; + int core_enabled; + int core_num_dim_ix; + int *core_num_dims; + int *core_dim_ixs; + int *core_offsets; + char *core_signature; + PyUFunc_TypeResolutionFunc *type_resolver; + PyUFunc_LegacyInnerLoopSelectionFunc *legacy_inner_loop_selector; + void *reserved2; + PyUFunc_MaskedInnerLoopSelectionFunc *masked_inner_loop_selector; npy_uint32 *op_flags; npy_uint32 *iter_flags; } PyUFuncObject; @@ -804,6 +816,51 @@ PyUFunc_Type User defined type numbers are always larger than :c:data:`NPY_USERDEF`. + .. c:member:: int PyUFuncObject.core_enabled + + 0 for scalar ufuncs; 1 for generalized ufuncs + + .. c:member:: int PyUFuncObject.core_num_dim_ix + + Number of distinct core dimension names in the signature + + .. c:member:: int *PyUFuncObject.core_num_dims + + Number of core dimensions of each argument + + .. c:member:: int *PyUFuncObject.core_dim_ixs + + Dimension indices in a flattened form; indices of argument ``k`` are + stored in ``core_dim_ixs[core_offsets[k] : core_offsets[k] + + core_numdims[k]]`` + + .. c:member:: int *PyUFuncObject.core_offsets + + Position of 1st core dimension of each argument in ``core_dim_ixs``, + equivalent to cumsum(``core_num_dims``) + + .. c:member:: char *PyUFuncObject.core_signature + + Core signature string + + .. c:member:: PyUFunc_TypeResolutionFunc *PyUFuncObject.type_resolver + + A function which resolves the types and fills an array with the dtypes + for the inputs and outputs + + .. c:member:: PyUFunc_LegacyInnerLoopSelectionFunc *PyUFuncObject.legacy_inner_loop_selector + + A function which returns an inner loop. The ``legacy`` in the name arises + because for NumPy 1.6 a better variant had been planned. This variant + has not yet come about. + + .. c:member:: void *PyUFuncObject.reserved2 + + For a possible future loop selector with a different signature. + + .. c:member:: PyUFunc_MaskedInnerLoopSelectionFunc *PyUFuncObject.masked_inner_loop_selector + + Function which returns a masked inner loop for the ufunc .. c:member:: npy_uint32 PyUFuncObject.op_flags diff --git a/doc/source/reference/c-api.ufunc.rst b/doc/source/reference/c-api.ufunc.rst index 8c2554a9e..07c7b0c80 100644 --- a/doc/source/reference/c-api.ufunc.rst +++ b/doc/source/reference/c-api.ufunc.rst @@ -85,12 +85,61 @@ Functions Must to an array of length *ntypes* containing :c:type:`PyUFuncGenericFunction` items. These items are pointers to functions that actually implement the underlying - (element-by-element) function :math:`N` times. + (element-by-element) function :math:`N` times with the following + signature: + + .. c:function:: void loopfunc( + char** args, npy_intp* dimensions, npy_intp* steps, void* data) + + *args* + + An array of pointers to the actual data for the input and output + arrays. The input arguments are given first followed by the output + arguments. + + *dimensions* + + A pointer to the size of the dimension over which this function is + looping. + + *steps* + + A pointer to the number of bytes to jump to get to the + next element in this dimension for each of the input and + output arguments. + + *data* + + Arbitrary data (extra arguments, function names, *etc.* ) + that can be stored with the ufunc and will be passed in + when it is called. + + This is an example of a func specialized for addition of doubles + returning doubles. + + .. code-block:: c + + static void + double_add(char **args, npy_intp *dimensions, npy_intp *steps, + void *extra) + { + npy_intp i; + npy_intp is1 = steps[0], is2 = steps[1]; + npy_intp os = steps[2], n = dimensions[0]; + char *i1 = args[0], *i2 = args[1], *op = args[2]; + for (i = 0; i < n; i++) { + *((double *)op) = *((double *)i1) + + *((double *)i2); + i1 += is1; + i2 += is2; + op += os; + } + } :param data: Should be ``NULL`` or a pointer to an array of size *ntypes* . This array may contain arbitrary extra-data to be passed to - the corresponding 1-d loop function in the func array. + the corresponding loop function in the func array. :param types: Length ``(nin + nout) * ntypes`` array of ``char`` encoding the @@ -102,6 +151,9 @@ Functions be ``(char[]) {5, 5, 0, 7, 7, 0}`` since ``NPY_INT32`` is 5, ``NPY_INT64`` is 7, and ``NPY_BOOL`` is 0. + The bit-width names can also be used (e.g. :c:data:`NPY_INT32`, + :c:data:`NPY_COMPLEX128` ) if desired. + :ref:`ufuncs.casting` will be used at runtime to find the first ``func`` callable by the input/output provided. @@ -114,14 +166,19 @@ Functions :param nout: The number of outputs + :param identity: + + Either :c:data:`PyUFunc_One`, :c:data:`PyUFunc_Zero`, + :c:data:`PyUFunc_None`. This specifies what should be returned when + an empty array is passed to the reduce method of the ufunc. + :param name: - The name for the ufunc. Specifying a name of 'add' or - 'multiply' enables a special behavior for integer-typed - reductions when no dtype is given. If the input type is an - integer (or boolean) data type smaller than the size of the - `numpy.int_` data type, it will be internally upcast to the - `numpy.int_` (or `numpy.uint`) - data type. + The name for the ufunc as a ``NULL`` terminated string. Specifying + a name of 'add' or 'multiply' enables a special behavior for + integer-typed reductions when no dtype is given. If the input type is an + integer (or boolean) data type smaller than the size of the `numpy.int_` + data type, it will be internally upcast to the `numpy.int_` (or + `numpy.uint`) data type. :param doc: Allows passing in a documentation string to be stored with the diff --git a/doc/source/reference/internals.code-explanations.rst b/doc/source/reference/internals.code-explanations.rst index ca81e1676..65553e07e 100644 --- a/doc/source/reference/internals.code-explanations.rst +++ b/doc/source/reference/internals.code-explanations.rst @@ -17,7 +17,7 @@ pieces of code. The purpose behind these explanations is to enable somebody to be able to understand the ideas behind the implementation somewhat more easily than just staring at the code. Perhaps in this way, the algorithms can be improved on, borrowed from, and/or -optimized. +optimized by more people. Memory model @@ -133,9 +133,9 @@ Broadcasting .. index:: single: broadcasting -In Numeric, broadcasting was implemented in several lines of code -buried deep in ufuncobject.c. In NumPy, the notion of broadcasting has -been abstracted so that it can be performed in multiple places. +In Numeric, the ancestor of Numpy, broadcasting was implemented in several +lines of code buried deep in ufuncobject.c. In NumPy, the notion of broadcasting +has been abstracted so that it can be performed in multiple places. Broadcasting is handled by the function :c:func:`PyArray_Broadcast`. This function requires a :c:type:`PyArrayMultiIterObject` (or something that is a binary equivalent) to be passed in. The :c:type:`PyArrayMultiIterObject` keeps diff --git a/doc/source/reference/routines.polynomials.classes.rst b/doc/source/reference/routines.polynomials.classes.rst index f44ddd46c..da0394305 100644 --- a/doc/source/reference/routines.polynomials.classes.rst +++ b/doc/source/reference/routines.polynomials.classes.rst @@ -35,11 +35,11 @@ degree :math:`n`, but could just as easily be the basis functions of any of the other classes. The convention for all the classes is that the coefficient :math:`c[i]` goes with the basis function of degree i. -All of the classes have the same methods, and especially they implement the -Python numeric operators +, -, \*, //, %, divmod, \*\*, ==, -and !=. The last two can be a bit problematic due to floating point -roundoff errors. We now give a quick demonstration of the various -operations using NumPy version 1.7.0. +All of the classes are immutable and have the same methods, and +especially they implement the Python numeric operators +, -, \*, //, %, +divmod, \*\*, ==, and !=. The last two can be a bit problematic due to +floating point roundoff errors. We now give a quick demonstration of the +various operations using NumPy version 1.7.0. Basics ------ @@ -187,6 +187,11 @@ Which gives the polynomial `p` in Chebyshev form. This works because the original polynomial. However, all the multiplications and divisions will be done using Chebyshev series, hence the type of the result. +It is intended that all polynomial instances are immutable, therefore +augmented operations (``+=``, ``-=``, etc.) and any other functionality that +would violate the immutablity of a polynomial instance are intentionally +unimplemented. + Calculus -------- diff --git a/doc/source/release.rst b/doc/source/release.rst index e7166a454..7f0197f3f 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -3,7 +3,10 @@ Release Notes ************* .. include:: ../release/1.16.0-notes.rst +.. include:: ../release/1.15.2-notes.rst +.. include:: ../release/1.15.1-notes.rst .. include:: ../release/1.15.0-notes.rst +.. include:: ../release/1.14.6-notes.rst .. include:: ../release/1.14.5-notes.rst .. include:: ../release/1.14.4-notes.rst .. include:: ../release/1.14.3-notes.rst diff --git a/doc/source/user/c-info.beyond-basics.rst b/doc/source/user/c-info.beyond-basics.rst index aee68f6e7..d4d941a5e 100644 --- a/doc/source/user/c-info.beyond-basics.rst +++ b/doc/source/user/c-info.beyond-basics.rst @@ -358,38 +358,6 @@ previously created. Then you call :c:func:`PyUFunc_RegisterLoopForType` this function is ``0`` if the process was successful and ``-1`` with an error condition set if it was not successful. -.. c:function:: int PyUFunc_RegisterLoopForType( \ - PyUFuncObject* ufunc, int usertype, PyUFuncGenericFunction function, \ - int* arg_types, void* data) - - *ufunc* - - The ufunc to attach this loop to. - - *usertype* - - The user-defined type this loop should be indexed under. This number - must be a user-defined type or an error occurs. - - *function* - - The ufunc inner 1-d loop. This function must have the signature as - explained in Section `3 <#sec-creating-a-new>`__ . - - *arg_types* - - (optional) If given, this should contain an array of integers of at - least size ufunc.nargs containing the data-types expected by the loop - function. The data will be copied into a NumPy-managed structure so - the memory for this argument should be deleted after calling this - function. If this is NULL, then it will be assumed that all data-types - are of type usertype. - - *data* - - (optional) Specify any optional data needed by the function which will - be passed when the function is called. - .. index:: pair: dtype; adding new diff --git a/doc/source/user/c-info.python-as-glue.rst b/doc/source/user/c-info.python-as-glue.rst index 750fdddf0..01d2a64d1 100644 --- a/doc/source/user/c-info.python-as-glue.rst +++ b/doc/source/user/c-info.python-as-glue.rst @@ -944,7 +944,7 @@ Linux system this is accomplished using:: Which creates a shared_library named code.so in the current directory. On Windows don't forget to either add ``__declspec(dllexport)`` in front of void on the line preceding each function definition, or write a -code.def file that lists the names of the functions to be exported. +``code.def`` file that lists the names of the functions to be exported. A suitable Python interface to this shared library should be constructed. To do this create a file named interface.py with the @@ -954,25 +954,25 @@ following lines at the top: __all__ = ['add', 'filter2d'] - import numpy as N + import numpy as np import os _path = os.path.dirname('__file__') - lib = N.ctypeslib.load_library('code', _path) - _typedict = {'zadd' : complex, 'sadd' : N.single, - 'cadd' : N.csingle, 'dadd' : float} + lib = np.ctypeslib.load_library('code', _path) + _typedict = {'zadd' : complex, 'sadd' : np.single, + 'cadd' : np.csingle, 'dadd' : float} for name in _typedict.keys(): val = getattr(lib, name) val.restype = None _type = _typedict[name] - val.argtypes = [N.ctypeslib.ndpointer(_type, + val.argtypes = [np.ctypeslib.ndpointer(_type, flags='aligned, contiguous'), - N.ctypeslib.ndpointer(_type, + np.ctypeslib.ndpointer(_type, flags='aligned, contiguous'), - N.ctypeslib.ndpointer(_type, + np.ctypeslib.ndpointer(_type, flags='aligned, contiguous,'\ 'writeable'), - N.ctypeslib.c_intp] + np.ctypeslib.c_intp] This code loads the shared library named ``code.{ext}`` located in the same path as this file. It then adds a return type of void to the @@ -989,13 +989,13 @@ strides and shape of an ndarray) as the last two arguments.: .. code-block:: python lib.dfilter2d.restype=None - lib.dfilter2d.argtypes = [N.ctypeslib.ndpointer(float, ndim=2, + lib.dfilter2d.argtypes = [np.ctypeslib.ndpointer(float, ndim=2, flags='aligned'), - N.ctypeslib.ndpointer(float, ndim=2, + np.ctypeslib.ndpointer(float, ndim=2, flags='aligned, contiguous,'\ 'writeable'), - ctypes.POINTER(N.ctypeslib.c_intp), - ctypes.POINTER(N.ctypeslib.c_intp)] + ctypes.POINTER(np.ctypeslib.c_intp), + ctypes.POINTER(np.ctypeslib.c_intp)] Next, define a simple selection function that chooses which addition function to call in the shared library based on the data-type: @@ -1020,11 +1020,11 @@ written simply as: def add(a, b): requires = ['CONTIGUOUS', 'ALIGNED'] - a = N.asanyarray(a) + a = np.asanyarray(a) func, dtype = select(a.dtype) - a = N.require(a, dtype, requires) - b = N.require(b, dtype, requires) - c = N.empty_like(a) + a = np.require(a, dtype, requires) + b = np.require(b, dtype, requires) + c = np.empty_like(a) func(a,b,c,a.size) return c @@ -1033,8 +1033,8 @@ and: .. code-block:: python def filter2d(a): - a = N.require(a, float, ['ALIGNED']) - b = N.zeros_like(a) + a = np.require(a, float, ['ALIGNED']) + b = np.zeros_like(a) lib.dfilter2d(a, b, a.ctypes.strides, a.ctypes.shape) return b diff --git a/doc/source/user/c-info.ufunc-tutorial.rst b/doc/source/user/c-info.ufunc-tutorial.rst index 788a3429f..96a73f9a6 100644 --- a/doc/source/user/c-info.ufunc-tutorial.rst +++ b/doc/source/user/c-info.ufunc-tutorial.rst @@ -893,9 +893,9 @@ Example NumPy ufunc with structured array dtype arguments This example shows how to create a ufunc for a structured array dtype. For the example we show a trivial ufunc for adding two arrays with dtype 'u8,u8,u8'. The process is a bit different from the other examples since -a call to PyUFunc_FromFuncAndData doesn't fully register ufuncs for +a call to :c:func:`PyUFunc_FromFuncAndData` doesn't fully register ufuncs for custom dtypes and structured array dtypes. We need to also call -PyUFunc_RegisterLoopForDescr to finish setting up the ufunc. +:c:func:`PyUFunc_RegisterLoopForDescr` to finish setting up the ufunc. We only give the C code as the setup.py file is exactly the same as the setup.py file in `Example NumPy ufunc for one dtype`_, except that @@ -1048,133 +1048,6 @@ The C file is given below. #endif } - -.. _`sec:PyUFunc-spec`: - -PyUFunc_FromFuncAndData Specification -===================================== - -What follows is the full specification of PyUFunc_FromFuncAndData, which -automatically generates a ufunc from a C function with the correct signature. - -.. seealso:: :c:func:`PyUFunc_FromFuncAndDataAndSignature` - -.. c:function:: PyObject *PyUFunc_FromFuncAndData( \ - PyUFuncGenericFunction* func, void** data, char* types, int ntypes, \ - int nin, int nout, int identity, char* name, char* doc, int unused) - - *func* - - A pointer to an array of 1-d functions to use. This array must be at - least ntypes long. Each entry in the array must be a - ``PyUFuncGenericFunction`` function. This function has the following - signature. An example of a valid 1d loop function is also given. - - .. c:function:: void loop1d( \ - char** args, npy_intp* dimensions, npy_intp* steps, void* data) - - *args* - - An array of pointers to the actual data for the input and output - arrays. The input arguments are given first followed by the output - arguments. - - *dimensions* - - A pointer to the size of the dimension over which this function is - looping. - - *steps* - - A pointer to the number of bytes to jump to get to the - next element in this dimension for each of the input and - output arguments. - - *data* - - Arbitrary data (extra arguments, function names, *etc.* ) - that can be stored with the ufunc and will be passed in - when it is called. - - .. code-block:: c - - static void - double_add(char **args, npy_intp *dimensions, npy_intp *steps, - void *extra) - { - npy_intp i; - npy_intp is1 = steps[0], is2 = steps[1]; - npy_intp os = steps[2], n = dimensions[0]; - char *i1 = args[0], *i2 = args[1], *op = args[2]; - for (i = 0; i < n; i++) { - *((double *)op) = *((double *)i1) + - *((double *)i2); - i1 += is1; - i2 += is2; - op += os; - } - } - - *data* - - An array of data. There should be ntypes entries (or NULL) --- one for - every loop function defined for this ufunc. This data will be passed - in to the 1-d loop. One common use of this data variable is to pass in - an actual function to call to compute the result when a generic 1-d - loop (e.g. :c:func:`PyUFunc_d_d`) is being used. - - *types* - - An array of type-number signatures (type ``char`` ). This - array should be of size (nin+nout)*ntypes and contain the - data-types for the corresponding 1-d loop. The inputs should - be first followed by the outputs. For example, suppose I have - a ufunc that supports 1 integer and 1 double 1-d loop - (length-2 func and data arrays) that takes 2 inputs and - returns 1 output that is always a complex double, then the - types array would be - - .. code-block:: c - - static char types[3] = {NPY_INT, NPY_DOUBLE, NPY_CDOUBLE} - - The bit-width names can also be used (e.g. :c:data:`NPY_INT32`, - :c:data:`NPY_COMPLEX128` ) if desired. - - *ntypes* - - The number of data-types supported. This is equal to the number of 1-d - loops provided. - - *nin* - - The number of input arguments. - - *nout* - - The number of output arguments. - - *identity* - - Either :c:data:`PyUFunc_One`, :c:data:`PyUFunc_Zero`, - :c:data:`PyUFunc_None`. This specifies what should be returned when - an empty array is passed to the reduce method of the ufunc. - - *name* - - A ``NULL`` -terminated string providing the name of this ufunc - (should be the Python name it will be called). - - *doc* - - A documentation string for this ufunc (will be used in generating the - response to ``{ufunc_name}.__doc__``). Do not include the function - signature or the name as this is generated automatically. - - *unused* - - Unused; kept for compatibility. Just set it to zero. - .. index:: pair: ufunc; adding new |