|
| 1 | + |
| 2 | +from ufunc_config_types import UFuncExtMod, UFunc, UFuncSource |
| 3 | + |
| 4 | + |
| 5 | +FIRST_DOCSTRING = """\ |
| 6 | +first(x, op, target, otherwise, /, ...) |
| 7 | +
|
| 8 | +Find the first value that matches the given comparison. |
| 9 | +""" |
| 10 | + |
| 11 | +ARGFIRST_DOCSTRING = """\ |
| 12 | +argfirst(x, op, target, /, ...) |
| 13 | +
|
| 14 | +Find the index in `x` of the first value where `x op target` |
| 15 | +is true, where `op` is one of the basic comparison operators. |
| 16 | +
|
| 17 | +Parameters |
| 18 | +---------- |
| 19 | +x : array_like, size (..., n) |
| 20 | + Array to be searched. |
| 21 | +op : int, one of {0, 1, 2, 3, 4, 5} |
| 22 | + Defines the comparison operation to be used. Attributes of |
| 23 | + the class `ufunclab.op` may be used as symbolic names of |
| 24 | + the operators. |
| 25 | +
|
| 26 | + Comparison op ufunclab.op attribute |
| 27 | + ---------- -- --------------------- |
| 28 | + < 0 ufunclab.op.LT |
| 29 | + <= 1 ufunclab.op.LE |
| 30 | + == 2 ufunclab.op.EQ |
| 31 | + != 3 ufunclab.op.NE |
| 32 | + > 4 ufunclab.op.GT |
| 33 | + >= 5 ufunclab.op.GE |
| 34 | +
|
| 35 | + An error is not raised if `op` is not in {0, 1, 2, 3, 4, 5}, |
| 36 | + but the return value will be -1. |
| 37 | +
|
| 38 | +target : value to be searched for |
| 39 | + For best efficiency, this value should have the same |
| 40 | + type as the elements of `x`. |
| 41 | +
|
| 42 | +Returns |
| 43 | +------- |
| 44 | +index : integer |
| 45 | + The index of the first element where the comparison |
| 46 | + is true. If no value is found, -1 is returned. |
| 47 | +
|
| 48 | +Examples |
| 49 | +-------- |
| 50 | +>>> import numpy as np |
| 51 | +>>> from ufunclab import argfirst, op |
| 52 | +
|
| 53 | +Find the index of the first occurrence of 0 in `x`: |
| 54 | +
|
| 55 | +>>> x = np.array([10, 35, 19, 0, -1, 24, 0]) |
| 56 | +>>> argfirst(x, op.EQ, 0) |
| 57 | +3 |
| 58 | +
|
| 59 | +Find the index of the first nonzero value in `a`: |
| 60 | +
|
| 61 | +>>> a = np.array([0, 0, 0, 0, 0, -0.5, 0, 1, 0.1]) |
| 62 | +>>> argfirst(a, op.NE, 0.0) |
| 63 | +5 |
| 64 | +
|
| 65 | +`argfirst` is a gufunc, so it can handle higher-dimensional |
| 66 | +array arguments, and among its gufunc-related parameters is |
| 67 | +`axis`. By default, the gufunc operates along the last axis. |
| 68 | +For example, here we find the location of the first nonzero |
| 69 | +element in each row of `b`: |
| 70 | +
|
| 71 | +>>> b = np.array([[0, 8, 0, 0], [0, 0, 0, 0], [0, 0, 9, 2]], |
| 72 | +... dtype=np.uint8) |
| 73 | +>>> b |
| 74 | +array([[0, 8, 0, 0], |
| 75 | + [0, 0, 0, 0], |
| 76 | + [0, 0, 9, 2]]) |
| 77 | +>>> argfirst(b, op.NE, np.uint8(0)) |
| 78 | +array([ 1, -1, 2]) |
| 79 | +
|
| 80 | +If we give the argument `axis=0`, we tell `argfirst` to |
| 81 | +operate along the first axis, which in this case is the |
| 82 | +columns: |
| 83 | +
|
| 84 | +>>> argfirst(b, op.NE, np.uint8(0), axis=0) |
| 85 | +array([-1, 0, 2, 2]) |
| 86 | +
|
| 87 | +""" |
| 88 | + |
| 89 | +first_src = UFuncSource( |
| 90 | + funcname='first_core_calc', |
| 91 | + typesignatures=[ |
| 92 | + 'bbbb->b', |
| 93 | + 'BbBB->B', |
| 94 | + 'hbhh->h', |
| 95 | + 'HbHH->H', |
| 96 | + 'ibii->i', |
| 97 | + 'IbII->I', |
| 98 | + 'lbll->l', |
| 99 | + 'LbLL->L', |
| 100 | + 'fbff->f', |
| 101 | + 'dbdd->d', |
| 102 | + 'gbgg->g', |
| 103 | + ] |
| 104 | +) |
| 105 | + |
| 106 | +first_src_object = UFuncSource( |
| 107 | + funcname='first_core_calc_object', |
| 108 | + typesignatures=['ObOO->O'] |
| 109 | +) |
| 110 | + |
| 111 | +first = UFunc( |
| 112 | + name='first', |
| 113 | + header='first_gufunc.h', |
| 114 | + docstring=FIRST_DOCSTRING, |
| 115 | + signature='(n),(),(),()->()', |
| 116 | + sources=[first_src, first_src_object], |
| 117 | +) |
| 118 | + |
| 119 | +argfirst_src = UFuncSource( |
| 120 | + funcname='argfirst_core_calc', |
| 121 | + typesignatures=[ |
| 122 | + 'bbb->l', |
| 123 | + 'BbB->l', |
| 124 | + 'hbh->l', |
| 125 | + 'HbH->l', |
| 126 | + 'ibi->l', |
| 127 | + 'IbI->l', |
| 128 | + 'lbl->l', |
| 129 | + 'LbL->l', |
| 130 | + 'fbf->l', |
| 131 | + 'dbd->l', |
| 132 | + 'gbg->l', |
| 133 | + ] |
| 134 | +) |
| 135 | + |
| 136 | +argfirst_src_object = UFuncSource( |
| 137 | + funcname='argfirst_core_calc_object', |
| 138 | + typesignatures=['ObO->l'] |
| 139 | +) |
| 140 | + |
| 141 | +argfirst = UFunc( |
| 142 | + name='argfirst', |
| 143 | + header='first_gufunc.h', |
| 144 | + docstring=ARGFIRST_DOCSTRING, |
| 145 | + signature='(n),(),()->()', |
| 146 | + sources=[argfirst_src, argfirst_src_object], |
| 147 | +) |
| 148 | + |
| 149 | +extmod = UFuncExtMod( |
| 150 | + module='_first', |
| 151 | + docstring=("This extension module defines the gufuncs 'first' and " |
| 152 | + "'argfirst'."), |
| 153 | + ufuncs=[first, argfirst], |
| 154 | + # The call `status = add_comparison_constants(module);` will be |
| 155 | + # added to the end of the module init function. |
| 156 | + extra_module_funcs=['add_comparison_constants'] |
| 157 | +) |
0 commit comments