Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/stats/intlist.pyx
8817 views
1
"""
2
C Int Lists
3
4
This is a class for fast basic operations with lists of C ints. It is
5
similar to the double precision TimeSeries class. It has all the
6
standard C int semantics, of course, including overflow. It is also
7
similar to the Python list class, except all elements are C ints,
8
which makes some operations much, much faster. For example,
9
concatenating two IntLists can be over 10 times faster than
10
concatenating the corresponding Python lists of ints, and taking
11
slices is also much faster.
12
13
AUTHOR:
14
15
- William Stein, 2010-03
16
"""
17
18
#############################################################################
19
# Copyright (C) 2010 William Stein <[email protected]>
20
# Distributed under the terms of the GNU General Public License (GPL), v2+.
21
# The full text of the GPL is available at:
22
# http://www.gnu.org/licenses/
23
#############################################################################
24
25
# Global parameter that sets the maximum number of entries of an IntList to print.
26
max_print = 10
27
28
29
# Imports
30
from sage.rings.integer import Integer
31
from sage.finance.time_series cimport TimeSeries
32
include "sage/ext/stdsage.pxi"
33
include "sage/ext/cdefs.pxi"
34
include "sage/ext/interrupt.pxi"
35
include "sage/ext/python_slice.pxi"
36
from cpython.string cimport *
37
38
cdef class IntList:
39
"""
40
A list of C int's.
41
"""
42
def __cinit__(self):
43
"""
44
Create new empty uninitialized IntList.
45
46
EXAMPLES::
47
48
sage: stats.IntList(5) # indirect test
49
[0, 0, 0, 0, 0]
50
51
"""
52
self._values = NULL
53
54
def __init__(self, values):
55
"""
56
Create an initialized list of C ints.
57
58
INPUT:
59
60
- values -- int, long, Integer, list of integers, or a TimeSeries
61
62
If the input is a time series or list of floats, then the
63
integer parts of the intries are taken (not the floor).
64
65
EXAMPLES::
66
67
sage: stats.IntList(8)
68
[0, 0, 0, 0, 0, 0, 0, 0]
69
70
sage: stats.IntList([1,5,-39392])
71
[1, 5, -39392]
72
73
We check for overflow when creating the IntList::
74
75
sage: stats.IntList([1, 3, 2^32])
76
Traceback (most recent call last):
77
...
78
OverflowError: ... too large to convert to C long # 32-bit
79
OverflowError: ... too large to convert to int # 64-bit
80
81
Printing omits entries::
82
83
sage: stats.IntList(1000)
84
[0, 0, 0, 0, 0 ... 0, 0, 0, 0, 0]
85
86
Floats are truncated to their integer parts::
87
88
sage: stats.IntList([1.1, -2.6])
89
[1, -2]
90
sage: stats.IntList(stats.TimeSeries([1.1, -2.6]))
91
[1, -2]
92
"""
93
cdef TimeSeries T
94
if isinstance(values, (int,long,Integer)):
95
self._length = values
96
values = None
97
elif PY_TYPE_CHECK(values, TimeSeries):
98
T = values
99
self._length = T._length
100
else:
101
self._length = len(values)
102
103
self._values = <int*> sage_malloc(sizeof(int)*self._length)
104
if self._values == NULL:
105
raise MemoryError
106
cdef Py_ssize_t i
107
if values is None:
108
for i in range(self._length):
109
self._values[i] = 0
110
elif PY_TYPE_CHECK(values, TimeSeries):
111
for i in range(self._length):
112
self._values[i] = <int> T._values[i]
113
else:
114
for i in range(self._length):
115
self._values[i] = values[i]
116
117
def __cmp__(self, _other):
118
"""
119
Compare self and other. This has the same semantics
120
as list comparison.
121
122
EXAMPLES:
123
sage: v = stats.IntList([1,2,3]); w = stats.IntList([1,2])
124
sage: v < w
125
False
126
sage: w < v
127
True
128
sage: v == v
129
True
130
sage: w == w
131
True
132
"""
133
cdef IntList other
134
cdef Py_ssize_t c, i
135
cdef int d
136
if not isinstance(_other, IntList):
137
_other = IntList(_other)
138
other = _other
139
for i in range(min(self._length, other._length)):
140
d = self._values[i] - other._values[i]
141
if d: return -1 if d < 0 else 1
142
c = self._length - other._length
143
if c < 0: return -1
144
elif c > 0: return 1
145
return 0
146
147
def __dealloc__(self):
148
"""
149
Deallocate memory used by the IntList, if it was allocated.
150
"""
151
if self._values:
152
sage_free(self._values)
153
154
def __repr__(self):
155
"""
156
Return string representation of this IntList.
157
158
EXAMPLES::
159
160
sage: a = stats.IntList([1..15]); a.__repr__()
161
'[1, 2, 3, 4, 5 ... 11, 12, 13, 14, 15]'
162
sage: sage.stats.intlist.max_print = 20
163
sage: a.__repr__()
164
'[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]'
165
sage: sage.stats.intlist.max_print = 10
166
sage: a.__repr__()
167
'[1, 2, 3, 4, 5 ... 11, 12, 13, 14, 15]'
168
"""
169
if len(self) > max_print:
170
v0 = self[:max_print//2]
171
v1 = self[-max_print//2:]
172
return '[' + ', '.join([str(x) for x in v0]) + ' ... ' + \
173
', '.join([str(x) for x in v1]) + ']'
174
else:
175
return str(self.list())
176
177
def __getitem__(self, i):
178
"""
179
Return i-th entry or slice of self, following standard Python
180
semantics. The returned slice is an intlist, and the returned
181
entry is a Python int.
182
183
INPUT:
184
185
- i -- integer or slice
186
187
EXAMPLES::
188
189
sage: a = stats.IntList([0..9]); a
190
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
191
sage: a[5]
192
5
193
sage: a[-2]
194
8
195
sage: a[5:-2]
196
[5, 6, 7]
197
sage: type(a[5:-2])
198
<type 'sage.stats.intlist.IntList'>
199
sage: type(a[5])
200
<type 'int'>
201
"""
202
cdef Py_ssize_t start, stop, step, j
203
cdef IntList t
204
if PySlice_Check(i):
205
start = 0 if (i.start is None) else i.start
206
stop = self._length if (i.stop is None) else i.stop
207
step = 1 if (i.step is None) else i.step
208
if start < 0:
209
start += self._length
210
if start < 0: start = 0
211
elif start >= self._length:
212
start = self._length - 1
213
if stop < 0:
214
stop += self._length
215
if stop < 0: stop = 0
216
elif stop > self._length:
217
stop = self._length
218
if start >= stop:
219
return new_int_list(0)
220
if step < 0:
221
step = -step
222
t = new_int_list((stop-start)/step)
223
for j from 0 <= j < (stop-start)/step:
224
t._values[j] = self._values[stop-1 - j*step]
225
elif step > 1:
226
t = new_int_list((stop-start)/step)
227
for j from 0 <= j < (stop-start)/step:
228
t._values[j] = self._values[j*step+start]
229
else:
230
t = new_int_list(stop-start)
231
memcpy(t._values, self._values + start, sizeof(int)*t._length)
232
return t
233
else:
234
j = i
235
if j < 0:
236
j += self._length
237
if j < 0:
238
raise IndexError, "IntList index out of range"
239
elif j >= self._length:
240
raise IndexError, "IntList index out of range"
241
return self._values[j]
242
243
def __setitem__(self, Py_ssize_t i, int x):
244
"""
245
Set the i-th entry of self, following standard Python semantics.
246
247
INPUT:
248
249
- i -- an integer
250
- x -- an int
251
252
EXAMPLES::
253
254
sage: a = stats.IntList([-2,3,7,-4])
255
sage: a[1] = 10393; a
256
[-2, 10393, 7, -4]
257
sage: a[-1] = -10; a
258
[-2, 10393, 7, -10]
259
sage: a[100]
260
Traceback (most recent call last):
261
...
262
IndexError: IntList index out of range
263
sage: a[-100]
264
Traceback (most recent call last):
265
...
266
IndexError: IntList index out of range
267
"""
268
if i < 0:
269
i += self._length
270
if i < 0:
271
raise IndexError, "index out of range"
272
elif i >= self._length:
273
raise IndexError, "index out of range"
274
self._values[i] = x
275
276
def __reduce__(self):
277
"""
278
Used in pickling int lists.
279
280
EXAMPLES::
281
282
sage: a = stats.IntList([-2,3,7,-4])
283
sage: loads(dumps(a)) == a
284
True
285
286
287
sage: v = stats.IntList([1,-3])
288
sage: v.__reduce__()
289
(<built-in function unpickle_intlist_v1>, ('...', 2))
290
sage: loads(dumps(v)) == v
291
True
292
293
Note that dumping and loading with compress False is much faster, though
294
dumping with compress True can save a lot of space::
295
296
sage: v = stats.IntList([1..10^5])
297
sage: loads(dumps(v, compress=False),compress=False) == v
298
True
299
300
"""
301
buf = PyString_FromStringAndSize(<char*>self._values, self._length*sizeof(int)/sizeof(char))
302
return unpickle_intlist_v1, (buf, self._length)
303
304
def list(self):
305
"""
306
Return Python list version of self with Python ints as entries.
307
308
EXAMPLES::
309
310
sage: a = stats.IntList([1..15]); a
311
[1, 2, 3, 4, 5 ... 11, 12, 13, 14, 15]
312
sage: a.list()
313
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
314
sage: list(a) == a.list()
315
True
316
sage: type(a.list()[0])
317
<type 'int'>
318
"""
319
cdef Py_ssize_t i
320
return [self._values[i] for i in range(self._length)]
321
322
cpdef int sum(self):
323
"""
324
Return the sum of the entries of self.
325
326
EXAMPLES::
327
328
sage: stats.IntList([1..100]).sum()
329
5050
330
331
Note that there can be overflow, since the entries are C ints::
332
333
sage: a = stats.IntList([2^30,2^30]); a
334
[1073741824, 1073741824]
335
sage: a.sum()
336
-2147483648
337
"""
338
cdef Py_ssize_t i
339
cdef int s=0
340
sig_on()
341
for i in range(self._length):
342
s += self._values[i]
343
sig_off()
344
return s
345
346
cpdef int prod(self):
347
"""
348
Return the product of the entries of self.
349
350
EXAMPLES::
351
352
sage: a = stats.IntList([1..10]); a
353
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
354
sage: a.prod()
355
3628800
356
sage: factorial(10)
357
3628800
358
359
Note that there can be overflow::
360
361
sage: a = stats.IntList([2^30, 2]); a
362
[1073741824, 2]
363
sage: a.prod()
364
-2147483648
365
"""
366
cdef Py_ssize_t i
367
cdef int s=1
368
sig_on()
369
for i in range(self._length):
370
s *= self._values[i]
371
sig_off()
372
return s
373
374
def __len__(self):
375
"""
376
Return the number of entries in this time series.
377
378
OUTPUT:
379
Python integer
380
381
EXAMPLES:
382
383
sage: len(stats.IntList([1..15]))
384
15
385
sage: len(stats.IntList([]))
386
0
387
sage: len(stats.IntList(10^6))
388
1000000
389
"""
390
return self._length
391
392
def __add__(left, right):
393
"""
394
Concatenate the integer lists self and right.
395
396
EXAMPLES::
397
398
sage: stats.IntList([-2,3,5]) + stats.IntList([1,1,17])
399
[-2, 3, 5, 1, 1, 17]
400
"""
401
if not isinstance(right, IntList):
402
raise TypeError, "right operand must be an int list"
403
if not isinstance(left, IntList):
404
raise TypeError, "left operand must be an int list"
405
cdef IntList R = right
406
cdef IntList L = left
407
cdef IntList t = new_int_list(L._length + R._length)
408
memcpy(t._values, L._values, sizeof(int)*L._length)
409
memcpy(t._values + L._length, R._values, sizeof(int)*R._length)
410
return t
411
412
def min(self, bint index=False):
413
"""
414
Return the smallest value in this integer list. If this
415
series has length 0 we raise a ValueError.
416
417
INPUT:
418
419
- index -- bool (default: False); if True, also return
420
index of minimal entry.
421
422
OUTPUT:
423
424
- float -- smallest value
425
- integer -- index of smallest value; only returned if
426
index=True
427
428
EXAMPLES::
429
430
sage: v = stats.IntList([1,-4,3,-2,-4])
431
sage: v.min()
432
-4
433
sage: v.min(index=True)
434
(-4, 1)
435
"""
436
if self._length == 0:
437
raise ValueError, "min() arg is an empty sequence"
438
cdef Py_ssize_t i, j
439
cdef int s = self._values[0]
440
j = 0
441
for i in range(1, self._length):
442
if self._values[i] < s:
443
s = self._values[i]
444
j = i
445
if index:
446
return s, j
447
else:
448
return s
449
450
def max(self, bint index=False):
451
"""
452
Return the largest value in this time series. If this series
453
has length 0 we raise a ValueError
454
455
INPUT:
456
457
- index -- bool (default: False); if True, also return
458
index of maximum entry.
459
460
OUTPUT:
461
462
- int -- largest value
463
- int -- index of largest value; only returned if index=True
464
465
EXAMPLES::
466
467
sage: v = stats.IntList([1,-4,3,-2,-4,3])
468
sage: v.max()
469
3
470
sage: v.max(index=True)
471
(3, 2)
472
"""
473
if self._length == 0:
474
raise ValueError, "max() arg is an empty sequence"
475
cdef Py_ssize_t i, j = 0
476
cdef int s = self._values[0]
477
for i in range(1,self._length):
478
if self._values[i] > s:
479
s = self._values[i]
480
j = i
481
if index:
482
return s, j
483
else:
484
return s
485
486
def time_series(self):
487
"""
488
Return TimeSeries version of self, which involves changing
489
each entry to a double.
490
491
EXAMPLES::
492
493
sage: T = stats.IntList([-2,3,5]).time_series(); T
494
[-2.0000, 3.0000, 5.0000]
495
sage: type(T)
496
<type 'sage.finance.time_series.TimeSeries'>
497
"""
498
cdef TimeSeries T = PY_NEW(TimeSeries)
499
# We just reach into the data structure underlying T, since we
500
# want this function to be *very* fast.
501
T._length = self._length
502
T._values = <double*> sage_malloc(sizeof(double)*self._length)
503
cdef Py_ssize_t i
504
for i in range(self._length):
505
T._values[i] = self._values[i]
506
return T
507
508
def plot(self, *args, **kwds):
509
"""
510
Return a plot of this IntList. This just constructs the
511
corresponding double-precision floating point TimeSeries
512
object, passing on all arguments.
513
514
EXAMPLES::
515
516
sage: stats.IntList([3,7,19,-2]).plot()
517
sage: stats.IntList([3,7,19,-2]).plot(color='red',pointsize=50,points=True)
518
"""
519
return self.time_series().plot(*args, **kwds)
520
521
def plot_histogram(self, *args, **kwds):
522
"""
523
Return a histogram plot of this IntList. This just constructs
524
the corresponding double-precision floating point TimeSeries object,
525
and plots it, passing on all arguments.
526
527
EXAMPLES::
528
529
sage: stats.IntList([1..15]).plot_histogram()
530
"""
531
return self.time_series().plot_histogram(*args, **kwds)
532
533
534
cdef IntList new_int_list(Py_ssize_t length):
535
"""
536
Function that is used internally to quickly create a new intlist
537
without initializing any of the allocated memory.
538
539
INPUT:
540
541
- length -- a nonnegative integer
542
543
OUTPUT:
544
545
- an IntList.
546
"""
547
if length < 0:
548
raise ValueError, "length must be nonnegative"
549
cdef IntList t = PY_NEW(IntList)
550
t._length = length
551
t._values = <int*> sage_malloc(sizeof(int)*length)
552
return t
553
554
555
def unpickle_intlist_v1(v, Py_ssize_t n):
556
"""
557
Version 1 unpickle method.
558
559
INPUT:
560
v -- a raw char buffer
561
562
EXAMPLES::
563
564
sage: v = stats.IntList([1,2,3])
565
sage: s = v.__reduce__()[1][0]
566
sage: type(s)
567
<type 'str'>
568
sage: sage.stats.intlist.unpickle_intlist_v1(s, 3)
569
[1, 2, 3]
570
sage: sage.stats.intlist.unpickle_intlist_v1(s+s,6)
571
[1, 2, 3, 1, 2, 3]
572
sage: sage.stats.intlist.unpickle_intlist_v1('',0)
573
[]
574
"""
575
cdef IntList t = new_int_list(n)
576
memcpy(t._values, PyString_AsString(v), n*sizeof(int))
577
return t
578
579