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