LSST Applications g0f08755f38+82efc23009,g12f32b3c4e+e7bdf1200e,g1653933729+a8ce1bb630,g1a0ca8cf93+50eff2b06f,g28da252d5a+52db39f6a5,g2bbee38e9b+37c5a29d61,g2bc492864f+37c5a29d61,g2cdde0e794+c05ff076ad,g3156d2b45e+41e33cbcdc,g347aa1857d+37c5a29d61,g35bb328faa+a8ce1bb630,g3a166c0a6a+37c5a29d61,g3e281a1b8c+fb992f5633,g414038480c+7f03dfc1b0,g41af890bb2+11b950c980,g5fbc88fb19+17cd334064,g6b1c1869cb+12dd639c9a,g781aacb6e4+a8ce1bb630,g80478fca09+72e9651da0,g82479be7b0+04c31367b4,g858d7b2824+82efc23009,g9125e01d80+a8ce1bb630,g9726552aa6+8047e3811d,ga5288a1d22+e532dc0a0b,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc28159a63d+37c5a29d61,gcf0d15dbbd+2acd6d4d48,gd7358e8bfb+778a810b6e,gda3e153d99+82efc23009,gda6a2b7d83+2acd6d4d48,gdaeeff99f8+1711a396fd,ge2409df99d+6b12de1076,ge79ae78c31+37c5a29d61,gf0baf85859+d0a5978c5a,gf3967379c6+4954f8c433,gfb92a5be7c+82efc23009,gfec2e1e490+2aaed99252,w.2024.46
LSST Data Management Base Package
Loading...
Searching...
No Matches
_rangeSet.cc
Go to the documentation of this file.
1/*
2 * This file is part of sphgeom.
3 *
4 * Developed for the LSST Data Management System.
5 * This product includes software developed by the LSST Project
6 * (http://www.lsst.org).
7 * See the COPYRIGHT file at the top-level directory of this distribution
8 * for details of code ownership.
9 *
10 * This software is dual licensed under the GNU General Public License and also
11 * under a 3-clause BSD license. Recipients may choose which of these licenses
12 * to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
13 * respectively. If you choose the GPL option then the following text applies
14 * (but note that there is still no warranty even if you opt for BSD instead):
15 *
16 * This program is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 */
29#include "pybind11/pybind11.h"
30
31#include "lsst/sphgeom/python.h"
32
35
36namespace py = pybind11;
37using namespace pybind11::literals;
38
39namespace lsst {
40namespace sphgeom {
41
42namespace {
43
45uint64_t _uint64(py::handle const &obj) {
46 try {
47 return obj.cast<uint64_t>();
48 } catch (py::cast_error const &) {
49 throw py::value_error(
50 "RangeSet elements and range beginning and "
51 "end points must be non-negative integers "
52 "less than 2**64");
53 }
54}
55
58RangeSet makeRangeSet(py::iterable iterable) {
59 RangeSet rs;
60 for (py::handle item : iterable) {
61 PyObject *o = item.ptr();
62 if (PySequence_Check(o) && PySequence_Size(o) == 2) {
63 uint64_t first = _uint64(py::reinterpret_steal<py::object>(
64 PySequence_GetItem(o, 0)));
65 uint64_t last = _uint64(py::reinterpret_steal<py::object>(
66 PySequence_GetItem(o, 1)));
67 rs.insert(first, last);
68 } else {
69 rs.insert(_uint64(item));
70 }
71 }
72 return rs;
73}
74
76py::list ranges(RangeSet const &self) {
77 py::list list;
78 for (auto t : self) {
79 list.append(py::make_tuple(py::int_(std::get<0>(t)),
80 py::int_(std::get<1>(t))));
81 }
82 return list;
83}
84
85// TODO: In C++, the end-point of a range containing 2**64 - 1 is 0, because
86// unsigned integer arithmetic is modular, and 2**64 does not fit in a
87// uint64_t. In Python, it would perhaps be nicer to map between C++
88// range end-point values of 0 and the Python integer 2**64. Since this is
89// somewhat involved, it is left as future work.
90
91} // <anonymous>
92
93template <>
95 cls.def(py::init<>());
96 cls.def(py::init<uint64_t>(), "integer"_a);
97 cls.def(py::init([](uint64_t a, uint64_t b) {
98 return new RangeSet(a, b);
99 }),
100 "first"_a, "last"_a);
101 cls.def(py::init<RangeSet const &>(), "rangeSet"_a);
102 cls.def(py::init(
103 [](py::iterable iterable) {
104 return new RangeSet(makeRangeSet(iterable));
105 }),
106 "iterable"_a);
107 cls.def("__eq__", &RangeSet::operator==, py::is_operator());
108 cls.def("__ne__", &RangeSet::operator!=, py::is_operator());
109
110 cls.def("insert", (void (RangeSet::*)(uint64_t)) & RangeSet::insert,
111 "integer"_a);
112 cls.def("insert",
113 (void (RangeSet::*)(uint64_t, uint64_t)) & RangeSet::insert,
114 "first"_a, "last"_a);
115 cls.def("erase", (void (RangeSet::*)(uint64_t)) & RangeSet::erase,
116 "integer"_a);
117 cls.def("erase", (void (RangeSet::*)(uint64_t, uint64_t)) & RangeSet::erase,
118 "first"_a, "last"_a);
119
120 cls.def("complement", &RangeSet::complement);
121 cls.def("complemented", &RangeSet::complemented);
122 cls.def("intersection", &RangeSet::intersection, "rangeSet"_a);
123 // In C++, the set union function is named join because union is a keyword.
124 // Python does not suffer from the same restriction.
125 cls.def("union", &RangeSet::join, "rangeSet"_a);
126 cls.def("difference", &RangeSet::difference, "rangeSet"_a);
127 cls.def("symmetricDifference", &RangeSet::symmetricDifference,
128 "rangeSet"_a);
129 cls.def("__invert__", &RangeSet::operator~, py::is_operator());
130 cls.def("__and__", &RangeSet::operator&, py::is_operator());
131 cls.def("__or__", &RangeSet::operator|, py::is_operator());
132 cls.def("__sub__", &RangeSet::operator-, py::is_operator());
133 cls.def("__xor__", &RangeSet::operator^, py::is_operator());
134 cls.def("__iand__", &RangeSet::operator&=);
135 cls.def("__ior__", &RangeSet::operator|=);
136 cls.def("__isub__", &RangeSet::operator-=);
137 cls.def("__ixor__", &RangeSet::operator^=);
138
139 cls.def("__len__", &RangeSet::size);
140 cls.def("__getitem__", [](RangeSet const &self, py::int_ i) {
141 auto j = python::convertIndex(static_cast<ptrdiff_t>(self.size()), i);
142 return py::cast(self.begin()[j]);
143 });
144
145 cls.def("intersects",
146 (bool (RangeSet::*)(uint64_t) const) & RangeSet::intersects,
147 "integer"_a);
148 cls.def("intersects",
149 (bool (RangeSet::*)(uint64_t, uint64_t) const) &
151 "first"_a, "last"_a);
152 cls.def("intersects",
153 (bool (RangeSet::*)(RangeSet const &) const) & RangeSet::intersects,
154 "rangeSet"_a);
155
156 cls.def("contains",
157 (bool (RangeSet::*)(uint64_t) const) & RangeSet::contains,
158 "integer"_a);
159 cls.def("contains",
160 (bool (RangeSet::*)(uint64_t, uint64_t) const) & RangeSet::contains,
161 "first"_a, "last"_a);
162 cls.def("contains",
163 (bool (RangeSet::*)(RangeSet const &) const) & RangeSet::contains,
164 "rangeSet"_a);
165 cls.def("__contains__",
166 (bool (RangeSet::*)(uint64_t) const) & RangeSet::contains,
167 "integer"_a, py::is_operator());
168 cls.def("__contains__",
169 (bool (RangeSet::*)(uint64_t, uint64_t) const) & RangeSet::contains,
170 "first"_a, "last"_a, py::is_operator());
171 cls.def("__contains__",
172 (bool (RangeSet::*)(RangeSet const &) const) & RangeSet::contains,
173 "rangeSet"_a, py::is_operator());
174
175 cls.def("isWithin",
176 (bool (RangeSet::*)(uint64_t) const) & RangeSet::isWithin,
177 "integer"_a);
178 cls.def("isWithin",
179 (bool (RangeSet::*)(uint64_t, uint64_t) const) & RangeSet::isWithin,
180 "first"_a, "last"_a);
181 cls.def("isWithin",
182 (bool (RangeSet::*)(RangeSet const &) const) & RangeSet::isWithin,
183 "rangeSet"_a);
184
185 cls.def("isDisjointFrom",
186 (bool (RangeSet::*)(uint64_t) const) & RangeSet::isDisjointFrom,
187 "integer"_a);
188 cls.def("isDisjointFrom",
189 (bool (RangeSet::*)(uint64_t, uint64_t) const) &
191 "first"_a, "last"_a);
192 cls.def("isDisjointFrom",
193 (bool (RangeSet::*)(RangeSet const &) const) &
195 "rangeSet"_a);
196
197 cls.def("simplify", &RangeSet::simplify, "n"_a);
198 cls.def("simplified", &RangeSet::simplified, "n"_a);
199 cls.def("scale", &RangeSet::scale, "factor"_a);
200 cls.def("scaled", &RangeSet::scaled, "factor"_a);
201 cls.def("fill", &RangeSet::fill);
202 cls.def("clear", &RangeSet::clear);
203 cls.def("empty", &RangeSet::empty);
204 cls.def("full", &RangeSet::full);
205 cls.def("size", &RangeSet::size);
206 cls.def("cardinality", &RangeSet::cardinality);
207 // max_size() and swap() are omitted. The former is a C++ container
208 // requirement, and the latter doesn't seem relevant to Python.
209 cls.def("isValid", &RangeSet::cardinality);
210 cls.def("ranges", &ranges);
211
212 cls.def("__str__",
213 [](RangeSet const &self) { return py::str(ranges(self)); });
214 cls.def("__repr__", [](RangeSet const &self) {
215 return py::str("RangeSet({!s})").format(ranges(self));
216 });
217
218 cls.def("__reduce__", [cls](RangeSet const &self) {
219 return py::make_tuple(cls, py::make_tuple(ranges(self)));
220 });
221}
222
223} // sphgeom
224} // lsst
This file provides a type for representing integer sets.
table::Key< int > b
A RangeSet is a set of unsigned 64 bit integers.
Definition RangeSet.h:106
RangeSet intersection(RangeSet const &s) const
intersection returns the intersection of this set and s.
Definition RangeSet.cc:142
std::uint64_t cardinality() const
cardinality returns the number of integers in this set.
Definition RangeSet.cc:307
void clear()
clear removes all integers from this set.
Definition RangeSet.h:508
bool full() const
full checks whether all integers in the universe of range sets, [0, 2^64), are in this set.
Definition RangeSet.h:518
RangeSet & scale(std::uint64_t i)
scale multiplies the endpoints of each range in this set by the given integer.
Definition RangeSet.cc:361
bool intersects(std::uint64_t u) const
Definition RangeSet.h:432
RangeSet join(RangeSet const &s) const
join returns the union of this set and s.
Definition RangeSet.cc:152
bool empty() const
empty checks whether there are any integers in this set.
Definition RangeSet.h:514
void erase(std::uint64_t u)
Definition RangeSet.h:313
bool contains(std::uint64_t u) const
Definition RangeSet.h:442
RangeSet & complement()
complement replaces this set S with U ∖ S, where U is the universe of range sets, [0,...
Definition RangeSet.h:335
bool isWithin(std::uint64_t u) const
Definition RangeSet.h:452
Iterator begin() const
Definition RangeSet.h:523
RangeSet simplified(std::uint32_t n) const
simplified returns a simplified copy of this set.
Definition RangeSet.h:486
size_t size() const
size returns the number of ranges in this set.
Definition RangeSet.h:546
bool isDisjointFrom(std::uint64_t u) const
Definition RangeSet.h:462
RangeSet & simplify(std::uint32_t n)
simplify simplifies this range set by "coarsening" its ranges.
Definition RangeSet.cc:315
void fill()
fill adds all the unsigned 64 bit integers to this set.
Definition RangeSet.h:511
RangeSet scaled(std::uint64_t i) const
scaled returns a scaled copy of this set.
Definition RangeSet.h:501
RangeSet complemented() const
complemented returns a complemented copy of this set.
Definition RangeSet.h:338
RangeSet difference(RangeSet const &s) const
difference returns the difference between this set and s.
Definition RangeSet.cc:164
RangeSet symmetricDifference(RangeSet const &s) const
symmetricDifference returns the symmetric difference of this set and s.
Definition RangeSet.cc:173
void insert(std::uint64_t u)
Definition RangeSet.h:292
daf::base::PropertyList * list
Definition fits.cc:932
ptrdiff_t convertIndex(ptrdiff_t len, pybind11::int_ i)
Convert a Python index i over a sequence with length len to a non-negative (C++ style) index,...
Definition utils.h:48
void defineClass(Pybind11Class &cls)