From c5002a58ffb4b3d25941e146dfb3ce6d4391c1de Mon Sep 17 00:00:00 2001 From: Guillaume Horel Date: Tue, 25 Apr 2023 13:57:27 -0400 Subject: add new packed format --- pyisda/curve.pxd | 5 +---- pyisda/curve.pyx | 47 +++++++++++++++++++++++++++++++++++++++-------- 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 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 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 = 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 = curve + memcpy(dst, src, sizeof(TCurve)) + src += sizeof(TCurve) + dst += sizeof(TCurve) + for i in range(curve.fNumItems): + (dst)[i] = (src)[i].fDate - curve.fBaseDate + ((dst + curve.fNumItems * sizeof(short)))[i] = (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 = 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 = malloc(size) memcpy(curve, src, size) state_size = size + elif fmt == 2: + n = (src).fNumItems + state_size = sizeof(TCurve) + n * (sizeof(TDate) + sizeof(double)) + curve = malloc(state_size) + memcpy(curve, src, sizeof(TCurve)) + base_date = (src).fBaseDate + curve += sizeof(TCurve) + src += sizeof(TCurve) + for i in range(n): + (curve)[i] = TRatePt(base_date + (src)[i], ((src + n * sizeof(short)))[i]) + curve -= sizeof(TCurve) instance.buf_size = state_size instance.buf.reset(curve, char_free) return instance -- cgit v1.2.3-70-g09d2