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