summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pyisda/curve.pxd5
-rw-r--r--pyisda/curve.pyx47
2 files changed, 40 insertions, 12 deletions
diff --git a/pyisda/curve.pxd b/pyisda/curve.pxd
index 8fb6733..d0d85f6 100644
--- a/pyisda/curve.pxd
+++ b/pyisda/curve.pxd
@@ -206,15 +206,12 @@ cdef extern from "survival_curve.hpp" nogil:
string full_ticker()
size_t size()
-cdef inline const TCurve* get_TCurve(Curve c) nogil:
- return <TCurve*>c.buf.get()
-
cdef class Curve:
cdef shared_ptr[char] buf
cdef readonly size_t buf_size
cdef inline const TCurve* get_TCurve(self) nogil
- cpdef bytes as_bytes(self, bint compressed)
+ cpdef bytes as_bytes(self, int fmt)
cdef class YieldCurve(Curve):
pass
diff --git a/pyisda/curve.pyx b/pyisda/curve.pyx
index 90df782..6dc66f1 100644
--- a/pyisda/curve.pyx
+++ b/pyisda/curve.pyx
@@ -1,5 +1,6 @@
from cython.operator import dereference as deref, preincrement as preinc
+from cpython.bytes cimport PyBytes_FromStringAndSize, PyBytes_AS_STRING
from libc.math cimport log1p, log, exp, isnan
from libc.string cimport strcpy, strncpy, strlen
from .date cimport (JpmcdsStringToDateInterval, pydate_to_TDate, dcc,
@@ -69,21 +70,40 @@ cdef class Curve(object):
cdef inline const TCurve* get_TCurve(self) nogil:
return <TCurve*>self.buf.get()
- cpdef bytes as_bytes(self, bint compressed):
+ cpdef bytes as_bytes(self, int fmt):
+ """ 0 uncompressed
+ 1 lz4 compressed
+ 2 packed
+ """
+
cdef:
bytes r
- int dst_capacity, compressed_size
+ int dst_capacity, compressed_size, i
char* dst
+ char* src
int size = self.buf_size
+ int packed_size
+ const TCurve* curve = self.get_TCurve()
- if compressed:
+ if fmt == 1:
dst_capacity = LZ4_compressBound(size)
dst = <char*>malloc(dst_capacity)
compressed_size = LZ4_compress_default(self.buf.get(), dst, size, dst_capacity)
r = dst[:compressed_size]
free(dst)
- else:
+ elif fmt == 0:
r = self.buf.get()[:self.buf_size]
+ elif fmt == 2:
+ packed_size = sizeof(TCurve) + curve.fNumItems * (sizeof(double) + sizeof(short))
+ r = PyBytes_FromStringAndSize(NULL, packed_size)
+ dst = PyBytes_AS_STRING(r)
+ src = <char*>curve
+ memcpy(dst, src, sizeof(TCurve))
+ src += sizeof(TCurve)
+ dst += sizeof(TCurve)
+ for i in range(curve.fNumItems):
+ (<short*>dst)[i] = (<TRatePt*>src)[i].fDate - curve.fBaseDate
+ (<double*>(dst + curve.fNumItems * sizeof(short)))[i] = (<TRatePt*>src)[i].fRate
return r
def __getstate__(self):
@@ -116,7 +136,7 @@ cdef class Curve(object):
self.buf.reset(curve, char_free)
@classmethod
- def from_bytes(cls, object state, bint compressed=True):
+ def from_bytes(cls, object state, int fmt=1):
cdef:
Curve instance = cls.__new__(cls)
Py_buffer* py_buf
@@ -126,7 +146,7 @@ cdef class Curve(object):
int decomp_size = 512
int retry = 0
TDate base_date
- double basis
+ size_t i, n
if PyMemoryView_Check(state):
py_buf = PyMemoryView_GET_BUFFER(state)
@@ -137,7 +157,7 @@ cdef class Curve(object):
size = PyBytes_GET_SIZE(state)
with nogil:
- if compressed:
+ if fmt == 1:
while True:
curve = <char*>realloc(curve, decomp_size)
state_size = LZ4_decompress_safe(src, curve, size, decomp_size)
@@ -150,10 +170,21 @@ cdef class Curve(object):
decomp_size *= 2
else:
break
- else:
+ elif fmt == 0:
curve = <char*>malloc(size)
memcpy(curve, src, size)
state_size = size
+ elif fmt == 2:
+ n = (<TCurve*>src).fNumItems
+ state_size = sizeof(TCurve) + n * (sizeof(TDate) + sizeof(double))
+ curve = <char*>malloc(state_size)
+ memcpy(curve, src, sizeof(TCurve))
+ base_date = (<TCurve*>src).fBaseDate
+ curve += sizeof(TCurve)
+ src += sizeof(TCurve)
+ for i in range(n):
+ (<TRatePt*>curve)[i] = TRatePt(base_date + (<short*>src)[i], (<double*>(src + n * sizeof(short)))[i])
+ curve -= sizeof(TCurve)
instance.buf_size = state_size
instance.buf.reset(curve, char_free)
return instance