1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright Contributors to the OpenEXR Project.
4 //
5
6 // clang-format off
7
8 #include <Python.h>
9 #include <boost/python.hpp>
10 #include <boost/python/make_constructor.hpp>
11 #include <boost/format.hpp>
12 #include "PyImathFun.h"
13 #include "PyImathFunOperators.h"
14 #include "PyImathDecorators.h"
15 #include "PyImathExport.h"
16 #include "PyImathAutovectorize.h"
17
18 namespace PyImath {
19
20 using namespace boost::python;
21
22 namespace
23 {
24
25 struct RegisterFloatDoubleOps
26 {
27 template <typename T>
operator ()PyImath::__anon5ec450510111::RegisterFloatDoubleOps28 void operator() (T)
29 {
30 // nb: MSVC gets confused about which arg we want (it thinks it
31 // might be boost::arg), so telling it which one explicitly here.
32 typedef boost::python::arg arg;
33
34 generate_bindings<abs_op<T>,boost::mpl::true_>(
35 "abs",
36 "return the absolute value of 'value'",
37 (arg("value")));
38
39 generate_bindings<sign_op<T>,boost::mpl::true_>(
40 "sign",
41 "return 1 or -1 based on the sign of 'value'",
42 (arg("value")));
43
44 generate_bindings<log_op<T>,boost::mpl::true_>(
45 "log",
46 "return the natural log of 'value'",
47 (arg("value")));
48
49 generate_bindings<log10_op<T>,boost::mpl::true_>(
50 "log10",
51 "return the base 10 log of 'value'",
52 (arg("value")));
53
54 generate_bindings<lerp_op<T>,boost::mpl::true_,boost::mpl::true_,boost::mpl::true_>(
55 "lerp",
56 "return the linear interpolation of 'a' to 'b' using parameter 't'",
57 (arg("a"),arg("b"),arg("t")));
58
59 generate_bindings<lerpfactor_op<T>,boost::mpl::true_,boost::mpl::true_,boost::mpl::true_>(
60 "lerpfactor",
61 "return how far m is between a and b, that is return t such that\n"
62 "if:\n"
63 " t = lerpfactor(m, a, b);\n"
64 "then:\n"
65 " m = lerp(a, b, t);\n"
66 "\n"
67 "If a==b, return 0.\n",
68 (arg("m"),arg("a"),arg("b")));
69
70 generate_bindings<clamp_op<T>,boost::mpl::true_,boost::mpl::true_,boost::mpl::true_>(
71 "clamp",
72 "return the value clamped to the range [low,high]",
73 (arg("value"),arg("low"),arg("high")));
74
75 generate_bindings<floor_op<T>,boost::mpl::true_>(
76 "floor",
77 "return the closest integer less than or equal to 'value'",
78 (arg("value")));
79
80 generate_bindings<ceil_op<T>,boost::mpl::true_>(
81 "ceil",
82 "return the closest integer greater than or equal to 'value'",
83 (arg("value")));
84
85 generate_bindings<trunc_op<T>,boost::mpl::true_>(
86 "trunc",
87 "return the closest integer with magnitude less than or equal to 'value'",
88 (arg("value")));
89
90 generate_bindings<rgb2hsv_op<T>,boost::mpl::true_>(
91 "rgb2hsv",
92 "return the hsv version of an rgb color",
93 args("rgb"));
94
95 generate_bindings<hsv2rgb_op<T>,boost::mpl::true_>(
96 "hsv2rgb",
97 "return the rgb version of an hsv color",
98 args("hsv"));
99
100 generate_bindings<sin_op<T>,boost::mpl::true_>(
101 "sin",
102 "return the sine of the angle theta",
103 args("theta"));
104
105 generate_bindings<cos_op<T>,boost::mpl::true_>(
106 "cos",
107 "return the cosine of the angle theta",
108 args("theta"));
109
110 generate_bindings<tan_op<T>,boost::mpl::true_>(
111 "tan",
112 "return the tangent of the angle theta",
113 args("theta"));
114
115 generate_bindings<asin_op<T>,boost::mpl::true_>(
116 "asin",
117 "return the arcsine of the value x",
118 args("x"));
119
120 generate_bindings<acos_op<T>,boost::mpl::true_>(
121 "acos",
122 "return the arccosine of the value x",
123 args("x"));
124
125 generate_bindings<atan_op<T>,boost::mpl::true_>(
126 "atan",
127 "return the arctangent of the value x",
128 args("x"));
129
130 generate_bindings<atan2_op<T>,boost::mpl::true_,boost::mpl::true_>(
131 "atan2",
132 "return the arctangent of the coordinate x,y - note the y "
133 "is the first argument for consistency with libm ordering",
134 args("y","x"));
135
136 generate_bindings<sqrt_op<T>,boost::mpl::true_>(
137 "sqrt",
138 "return the square root of x",
139 args("x"));
140
141 generate_bindings<pow_op<T>,boost::mpl::true_,boost::mpl::true_>(
142 "pow",
143 "return x**y",
144 args("x","y"));
145
146 generate_bindings<exp_op<T>,boost::mpl::true_>(
147 "exp",
148 "return exp(x)",
149 args("x"));
150
151 generate_bindings<sinh_op<T>,boost::mpl::true_>(
152 "sinh",
153 "return sinh(x)",
154 args("x"));
155
156 generate_bindings<cosh_op<T>,boost::mpl::true_>(
157 "cosh",
158 "return cosh(x)",
159 args("x"));
160
161 def("cmp", IMATH_NAMESPACE::cmp<T>);
162 def("cmpt", IMATH_NAMESPACE::cmpt<T>);
163 def("iszero", IMATH_NAMESPACE::iszero<T>);
164 def("equal", IMATH_NAMESPACE::equal<T, T, T>);
165 }
166 };
167
168 } // namespace
169
register_functions()170 void register_functions()
171 {
172 //
173 // Utility Functions
174 //
175
176 // nb: MSVC gets confused about which arg we want (it thinks it
177 // might be boost::arg), so telling it which one explicitly here.
178 typedef boost::python::arg arg;
179
180 using fp_types = boost::mpl::vector<float, double>;
181 boost::mpl::for_each<fp_types>(RegisterFloatDoubleOps());
182
183 generate_bindings<abs_op<int>,boost::mpl::true_>(
184 "abs",
185 "return the absolute value of 'value'",
186 (arg("value")));
187
188 generate_bindings<sign_op<int>,boost::mpl::true_>(
189 "sign",
190 "return 1 or -1 based on the sign of 'value'",
191 (arg("value")));
192
193 generate_bindings<clamp_op<int>,boost::mpl::true_,boost::mpl::true_,boost::mpl::true_>(
194 "clamp",
195 "return the value clamped to the range [low,high]",
196 (arg("value"),arg("low"),arg("high")));
197
198 generate_bindings<divs_op,boost::mpl::true_,boost::mpl::true_>(
199 "divs",
200 "return x/y where the remainder has the same sign as x:\n"
201 " divs(x,y) == (abs(x) / abs(y)) * (sign(x) * sign(y))\n",
202 (arg("x"),arg("y")));
203 generate_bindings<mods_op,boost::mpl::true_,boost::mpl::true_>(
204 "mods",
205 "return x%y where the remainder has the same sign as x:\n"
206 " mods(x,y) == x - y * divs(x,y)\n",
207 (arg("x"),arg("y")));
208
209 generate_bindings<divp_op,boost::mpl::true_,boost::mpl::true_>(
210 "divp",
211 "return x/y where the remainder is always positive:\n"
212 " divp(x,y) == floor (double(x) / double (y))\n",
213 (arg("x"),arg("y")));
214 generate_bindings<modp_op,boost::mpl::true_,boost::mpl::true_>(
215 "modp",
216 "return x%y where the remainder is always positive:\n"
217 " modp(x,y) == x - y * divp(x,y)\n",
218 (arg("x"),arg("y")));
219
220 generate_bindings<bias_op,boost::mpl::true_,boost::mpl::true_>(
221 "bias",
222 "bias(x,b) is a gamma correction that remaps the unit interval such that bias(0.5, b) = b.",
223 (arg("x"),arg("b")));
224
225 generate_bindings<gain_op,boost::mpl::true_,boost::mpl::true_>(
226 "gain",
227 "gain(x,g) is a gamma correction that remaps the unit interval with the property that gain(0.5, g) = 0.5.\n"
228 "The gain function can be thought of as two scaled bias curves forming an 'S' shape in the unit interval.",
229 (arg("x"),arg("g")));
230
231 //
232 // Vectorized utility functions
233 //
234 generate_bindings<rotationXYZWithUpDir_op<float>,boost::mpl::true_,boost::mpl::true_,boost::mpl::true_>(
235 "rotationXYZWithUpDir",
236 "return the XYZ rotation vector that rotates 'fromDir' to 'toDir'"
237 "using the up vector 'upDir'",
238 args("fromDir","toDir","upDir"));
239 }
240
241 } // namespace PyImath
242