Skip to content

Commit 1aa55d8

Browse files
committed
Merge branch 'c_inline' of https://github.com/wuan/pandas into wuan-c_inline
2 parents 3d1762b + 86c7e48 commit 1aa55d8

File tree

5 files changed

+75
-86
lines changed

5 files changed

+75
-86
lines changed

pandas/src/helper.h

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef C_HELPER_H
2+
#define C_HELPER_H
3+
4+
#ifndef PANDAS_INLINE
5+
#if defined(__GNUC__)
6+
#define PANDAS_INLINE __inline__
7+
#elif defined(_MSC_VER)
8+
#define PANDAS_INLINE __inline
9+
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
10+
#define PANDAS_INLINE inline
11+
#else
12+
#define PANDAS_INLINE
13+
#endif
14+
#endif
15+
16+
#endif

pandas/src/numpy_helper.h

+1-12
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,7 @@
11
#include "Python.h"
22
#include "numpy/arrayobject.h"
33
#include "numpy/arrayscalars.h"
4-
5-
#ifndef PANDAS_INLINE
6-
#if defined(__GNUC__)
7-
#define PANDAS_INLINE __inline__
8-
#elif defined(_MSC_VER)
9-
#define PANDAS_INLINE __inline
10-
#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
11-
#define PANDAS_INLINE inline
12-
#else
13-
#define PANDAS_INLINE
14-
#endif
15-
#endif
4+
#include "helper.h"
165

176
#define PANDAS_FLOAT 0
187
#define PANDAS_INT 1

pandas/src/period.c

+52-72
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
* Code derived from scikits.timeseries
1414
* ------------------------------------------------------------------*/
1515

16-
1716
static int mod_compat(int x, int m) {
1817
int result = x % m;
1918
if (result < 0) return result + m;
@@ -285,19 +284,19 @@ static int daytime_conversion_factors[][2] = {
285284

286285
static npy_int64** daytime_conversion_factor_matrix = NULL;
287286

288-
static int max_value(int a, int b) {
287+
PANDAS_INLINE static int max_value(int a, int b) {
289288
return a > b ? a : b;
290289
}
291290

292-
static int min_value(int a, int b) {
291+
PANDAS_INLINE static int min_value(int a, int b) {
293292
return a < b ? a : b;
294293
}
295294

296-
static int get_freq_group(int freq) {
295+
PANDAS_INLINE static int get_freq_group(int freq) {
297296
return (freq/1000)*1000;
298297
}
299298

300-
static int get_freq_group_index(int freq) {
299+
PANDAS_INLINE static int get_freq_group_index(int freq) {
301300
return freq/1000;
302301
}
303302

@@ -374,56 +373,39 @@ static void populate_conversion_factors_matrix() {
374373
}
375374
}
376375

377-
static void initialize_daytime_conversion_factor_maxtrix() {
378-
int matrix_size = calc_conversion_factors_matrix_size();
379-
alloc_conversion_factors_matrix(matrix_size);
380-
populate_conversion_factors_matrix();
381-
}
382-
383-
npy_int64 get_daytime_conversion_factor(int index1, int index2)
384-
{
376+
void initialize_daytime_conversion_factor_matrix() {
385377
if (daytime_conversion_factor_matrix == NULL) {
386-
initialize_daytime_conversion_factor_maxtrix();
378+
int matrix_size = calc_conversion_factors_matrix_size();
379+
alloc_conversion_factors_matrix(matrix_size);
380+
populate_conversion_factors_matrix();
387381
}
388-
return daytime_conversion_factor_matrix[min_value(index1, index2)][max_value(index1, index2)];
389382
}
390383

391-
npy_int64 convert_daytime(npy_int64 ordinal, int from, int to, int atEnd)
384+
PANDAS_INLINE npy_int64 get_daytime_conversion_factor(int from_index, int to_index)
392385
{
393-
int from_index, to_index, offset;
394-
npy_int64 conversion_factor;
395-
396-
if (from == to) {
397-
return ordinal;
398-
}
399-
400-
from_index = get_freq_group_index(from);
401-
to_index = get_freq_group_index(to);
402-
403-
conversion_factor = get_daytime_conversion_factor(from_index, to_index);
404-
405-
offset = atEnd ? 1 : 0;
386+
return daytime_conversion_factor_matrix[min_value(from_index, to_index)][max_value(from_index, to_index)];
387+
}
406388

407-
if (from <= to) {
408-
return (ordinal + offset) * conversion_factor - offset;
389+
PANDAS_INLINE npy_int64 upsample_daytime(npy_int64 ordinal, asfreq_info *af_info, int atEnd)
390+
{
391+
if (atEnd) {
392+
return (ordinal + 1) * af_info->intraday_conversion_factor - 1;
409393
} else {
410-
return ordinal / conversion_factor;
394+
return ordinal * af_info->intraday_conversion_factor;
411395
}
412-
413396
}
414397

415-
static npy_int64 transform_via_day(npy_int64 ordinal, char relation, asfreq_info *af_info, freq_conv_func first_func, freq_conv_func second_func) {
416-
int tempStore = af_info->targetFreq;
398+
PANDAS_INLINE npy_int64 downsample_daytime(npy_int64 ordinal, asfreq_info *af_info, int atEnd)
399+
{
400+
return ordinal / (af_info->intraday_conversion_factor);
401+
}
402+
403+
PANDAS_INLINE static npy_int64 transform_via_day(npy_int64 ordinal, char relation, asfreq_info *af_info, freq_conv_func first_func, freq_conv_func second_func) {
404+
//printf("transform_via_day(%ld, %ld, %d)\n", ordinal, af_info->intraday_conversion_factor, af_info->intraday_conversion_upsample);
417405
npy_int64 result;
418406

419-
af_info->targetFreq = FR_DAY;
420407
result = (*first_func)(ordinal, relation, af_info);
421-
af_info->targetFreq = tempStore;
422-
423-
tempStore = af_info->sourceFreq;
424-
af_info->sourceFreq = FR_DAY;
425408
result = (*second_func)(result, relation, af_info);
426-
af_info->sourceFreq = tempStore;
427409

428410
return result;
429411
}
@@ -460,7 +442,7 @@ static npy_int64 absdate_from_ymd(int y, int m, int d) {
460442

461443
static npy_int64 asfreq_DTtoA(npy_int64 ordinal, char relation, asfreq_info *af_info) {
462444
struct date_info dinfo;
463-
ordinal = convert_daytime(ordinal, af_info->sourceFreq, FR_DAY, 0);
445+
ordinal = downsample_daytime(ordinal, af_info, 0);
464446
if (dInfoCalc_SetFromAbsDate(&dinfo, ordinal + ORD_OFFSET, GREGORIAN_CALENDAR))
465447
return INT_ERR_CODE;
466448
if (dinfo.month > af_info->to_a_year_end) {
@@ -491,7 +473,7 @@ static npy_int64 DtoQ_yq(npy_int64 ordinal, asfreq_info *af_info, int *year, int
491473
static npy_int64 asfreq_DTtoQ(npy_int64 ordinal, char relation, asfreq_info *af_info) {
492474
int year, quarter;
493475

494-
ordinal = convert_daytime(ordinal, af_info->sourceFreq, FR_DAY, 0);
476+
ordinal = downsample_daytime(ordinal, af_info, 0);
495477

496478
if (DtoQ_yq(ordinal, af_info, &year, &quarter) == INT_ERR_CODE) {
497479
return INT_ERR_CODE;
@@ -503,22 +485,22 @@ static npy_int64 asfreq_DTtoQ(npy_int64 ordinal, char relation, asfreq_info *af_
503485
static npy_int64 asfreq_DTtoM(npy_int64 ordinal, char relation, asfreq_info *af_info) {
504486
struct date_info dinfo;
505487

506-
ordinal = convert_daytime(ordinal, af_info->sourceFreq, FR_DAY, 0);
488+
ordinal = downsample_daytime(ordinal, af_info, 0);
507489

508490
if (dInfoCalc_SetFromAbsDate(&dinfo, ordinal + ORD_OFFSET, GREGORIAN_CALENDAR))
509491
return INT_ERR_CODE;
510492
return (npy_int64)((dinfo.year - BASE_YEAR) * 12 + dinfo.month - 1);
511493
}
512494

513495
static npy_int64 asfreq_DTtoW(npy_int64 ordinal, char relation, asfreq_info *af_info) {
514-
ordinal = convert_daytime(ordinal, af_info->sourceFreq, FR_DAY, 0);
496+
ordinal = downsample_daytime(ordinal, af_info, 0);
515497
return (ordinal + ORD_OFFSET - (1 + af_info->to_week_end))/7 + 1 - WEEK_OFFSET;
516498
}
517499

518500
static npy_int64 asfreq_DTtoB(npy_int64 ordinal, char relation, asfreq_info *af_info) {
519501
struct date_info dinfo;
520502

521-
ordinal = convert_daytime(ordinal, af_info->sourceFreq, FR_DAY, 0);
503+
ordinal = downsample_daytime(ordinal, af_info, 0);
522504

523505
if (dInfoCalc_SetFromAbsDate(&dinfo, ordinal + ORD_OFFSET, GREGORIAN_CALENDAR))
524506
return INT_ERR_CODE;
@@ -531,14 +513,13 @@ static npy_int64 asfreq_DTtoB(npy_int64 ordinal, char relation, asfreq_info *af_
531513
}
532514

533515
// all intra day calculations are now done within one function
534-
static npy_int64 asfreq_WithinDT(npy_int64 ordinal, char relation, asfreq_info *af_info) {
535-
//if (relation == 'E') {
536-
// ordinal += 1;
537-
//}
538-
539-
return convert_daytime(ordinal, af_info->sourceFreq, af_info->targetFreq, relation == 'E');
516+
static npy_int64 asfreq_DownsampleWithinDay(npy_int64 ordinal, char relation, asfreq_info *af_info) {
517+
return downsample_daytime(ordinal, af_info, relation == 'E');
540518
}
541519

520+
static npy_int64 asfreq_UpsampleWithinDay(npy_int64 ordinal, char relation, asfreq_info *af_info) {
521+
return upsample_daytime(ordinal, af_info, relation == 'E');
522+
}
542523
//************ FROM BUSINESS ***************
543524

544525
static npy_int64 asfreq_BtoDT(npy_int64 ordinal, char relation, asfreq_info *af_info)
@@ -547,7 +528,7 @@ static npy_int64 asfreq_BtoDT(npy_int64 ordinal, char relation, asfreq_info *af_
547528
ordinal = (((ordinal - 1) / 5) * 7 +
548529
mod_compat(ordinal - 1, 5) + 1 - ORD_OFFSET);
549530

550-
return convert_daytime(ordinal, FR_DAY, af_info->targetFreq, relation != 'S');
531+
return upsample_daytime(ordinal, af_info, relation != 'S');
551532
}
552533

553534
static npy_int64 asfreq_BtoA(npy_int64 ordinal, char relation, asfreq_info *af_info) {
@@ -580,7 +561,7 @@ static npy_int64 asfreq_WtoDT(npy_int64 ordinal, char relation, asfreq_info *af_
580561
ordinal -= 1;
581562
}
582563

583-
return convert_daytime(ordinal, FR_DAY, af_info->targetFreq, relation != 'S');
564+
return upsample_daytime(ordinal, af_info, relation != 'S');
584565
}
585566

586567
static npy_int64 asfreq_WtoA(npy_int64 ordinal, char relation, asfreq_info *af_info) {
@@ -602,12 +583,9 @@ static npy_int64 asfreq_WtoW(npy_int64 ordinal, char relation, asfreq_info *af_i
602583
static npy_int64 asfreq_WtoB(npy_int64 ordinal, char relation, asfreq_info *af_info) {
603584

604585
struct date_info dinfo;
605-
int tempStore = af_info->targetFreq;
606-
af_info->targetFreq = FR_DAY;
607586
if (dInfoCalc_SetFromAbsDate(&dinfo,
608587
asfreq_WtoDT(ordinal, relation, af_info) + ORD_OFFSET,
609588
GREGORIAN_CALENDAR)) return INT_ERR_CODE;
610-
af_info->targetFreq = tempStore;
611589

612590
if (relation == 'S') {
613591
return DtoB_WeekendToMonday(dinfo.absdate, dinfo.day_of_week);
@@ -639,7 +617,7 @@ static npy_int64 asfreq_MtoDT(npy_int64 ordinal, char relation, asfreq_info* af_
639617
ordinal -= 1;
640618
}
641619

642-
return convert_daytime(ordinal, FR_DAY, af_info->targetFreq, relation != 'S');
620+
return upsample_daytime(ordinal, af_info, relation != 'S');
643621
}
644622

645623
static npy_int64 asfreq_MtoA(npy_int64 ordinal, char relation, asfreq_info *af_info) {
@@ -657,12 +635,9 @@ static npy_int64 asfreq_MtoW(npy_int64 ordinal, char relation, asfreq_info *af_i
657635
static npy_int64 asfreq_MtoB(npy_int64 ordinal, char relation, asfreq_info *af_info) {
658636
struct date_info dinfo;
659637

660-
int tempStore = af_info->targetFreq;
661-
af_info->targetFreq = FR_DAY;
662638
if (dInfoCalc_SetFromAbsDate(&dinfo,
663639
asfreq_MtoDT(ordinal, relation, af_info) + ORD_OFFSET,
664640
GREGORIAN_CALENDAR)) return INT_ERR_CODE;
665-
af_info->targetFreq = tempStore;
666641

667642
if (relation == 'S') { return DtoB_WeekendToMonday(dinfo.absdate, dinfo.day_of_week); }
668643
else { return DtoB_WeekendToFriday(dinfo.absdate, dinfo.day_of_week); }
@@ -698,7 +673,7 @@ static npy_int64 asfreq_QtoDT(npy_int64 ordinal, char relation, asfreq_info *af_
698673
absdate -= 1;
699674
}
700675

701-
return convert_daytime(absdate - ORD_OFFSET, FR_DAY, af_info->targetFreq, relation != 'S');
676+
return upsample_daytime(absdate - ORD_OFFSET, af_info, relation != 'S');
702677
}
703678

704679
static npy_int64 asfreq_QtoQ(npy_int64 ordinal, char relation, asfreq_info *af_info) {
@@ -720,12 +695,9 @@ static npy_int64 asfreq_QtoW(npy_int64 ordinal, char relation, asfreq_info *af_i
720695
static npy_int64 asfreq_QtoB(npy_int64 ordinal, char relation, asfreq_info *af_info) {
721696

722697
struct date_info dinfo;
723-
int tempStore = af_info->targetFreq;
724-
af_info->targetFreq = FR_DAY;
725698
if (dInfoCalc_SetFromAbsDate(&dinfo,
726699
asfreq_QtoDT(ordinal, relation, af_info) + ORD_OFFSET,
727700
GREGORIAN_CALENDAR)) return INT_ERR_CODE;
728-
af_info->targetFreq = tempStore;
729701

730702
if (relation == 'S') { return DtoB_WeekendToMonday(dinfo.absdate, dinfo.day_of_week); }
731703
else { return DtoB_WeekendToFriday(dinfo.absdate, dinfo.day_of_week); }
@@ -761,7 +733,7 @@ static npy_int64 asfreq_AtoDT(npy_int64 year, char relation, asfreq_info *af_inf
761733
absdate -= 1;
762734
}
763735

764-
return convert_daytime(absdate - ORD_OFFSET, FR_DAY, af_info->targetFreq, relation != 'S');
736+
return upsample_daytime(absdate - ORD_OFFSET, af_info, relation != 'S');
765737
}
766738

767739
static npy_int64 asfreq_AtoA(npy_int64 ordinal, char relation, asfreq_info *af_info) {
@@ -783,12 +755,9 @@ static npy_int64 asfreq_AtoW(npy_int64 ordinal, char relation, asfreq_info *af_i
783755
static npy_int64 asfreq_AtoB(npy_int64 ordinal, char relation, asfreq_info *af_info) {
784756

785757
struct date_info dinfo;
786-
int tempStore = af_info->targetFreq;
787-
af_info->targetFreq = FR_DAY;
788758
if (dInfoCalc_SetFromAbsDate(&dinfo,
789759
asfreq_AtoDT(ordinal, relation, af_info) + ORD_OFFSET,
790760
GREGORIAN_CALENDAR)) return INT_ERR_CODE;
791-
af_info->targetFreq = tempStore;
792761

793762
if (relation == 'S') { return DtoB_WeekendToMonday(dinfo.absdate, dinfo.day_of_week); }
794763
else { return DtoB_WeekendToFriday(dinfo.absdate, dinfo.day_of_week); }
@@ -813,8 +782,13 @@ void get_asfreq_info(int fromFreq, int toFreq, asfreq_info *af_info) {
813782
int fromGroup = get_freq_group(fromFreq);
814783
int toGroup = get_freq_group(toFreq);
815784

816-
af_info->sourceFreq = fromFreq;
817-
af_info->targetFreq = toFreq;
785+
af_info->intraday_conversion_factor =
786+
get_daytime_conversion_factor(
787+
get_freq_group_index(max_value(fromGroup, FR_DAY)),
788+
get_freq_group_index(max_value(toGroup, FR_DAY))
789+
);
790+
791+
//printf("get_asfreq_info(%d, %d) %ld, %d\n", fromFreq, toFreq, af_info->intraday_conversion_factor, af_info->intraday_conversion_upsample);
818792

819793
switch(fromGroup)
820794
{
@@ -970,7 +944,11 @@ freq_conv_func get_asfreq_func(int fromFreq, int toFreq)
970944
case FR_MS:
971945
case FR_US:
972946
case FR_NS:
973-
return &asfreq_WithinDT;
947+
if (fromGroup > toGroup) {
948+
return &asfreq_DownsampleWithinDay;
949+
} else {
950+
return &asfreq_UpsampleWithinDay;
951+
}
974952
default: return &nofunc;
975953
}
976954

@@ -1073,6 +1051,8 @@ npy_int64 asfreq(npy_int64 period_ordinal, int freq1, int freq2, char relation)
10731051

10741052
get_asfreq_info(freq1, freq2, &finfo);
10751053

1054+
//printf("\n%x %d %d %ld %ld\n", func, freq1, freq2, finfo.intraday_conversion_factor, -finfo.intraday_conversion_factor);
1055+
10761056
val = (*func)(period_ordinal, relation, &finfo);
10771057

10781058
if (val == INT_ERR_CODE) {

pandas/src/period.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define C_PERIOD_H
99

1010
#include <Python.h>
11+
#include "helper.h"
1112
#include "numpy/ndarraytypes.h"
1213
#include "headers/stdint.h"
1314
#include "limits.h"
@@ -106,8 +107,7 @@ typedef struct asfreq_info {
106107
int from_q_year_end; // month the year ends on in the "from" frequency
107108
int to_q_year_end; // month the year ends on in the "to" frequency
108109

109-
int sourceFreq;
110-
int targetFreq;
110+
npy_int64 intraday_conversion_factor;
111111
} asfreq_info;
112112

113113

@@ -162,4 +162,5 @@ double getAbsTime(int freq, npy_int64 dailyDate, npy_int64 originalDate);
162162
char *c_strftime(struct date_info *dinfo, char *fmt);
163163
int get_yq(npy_int64 ordinal, int freq, int *quarter, int *year);
164164

165+
void initialize_daytime_conversion_factor_matrix();
165166
#endif

pandas/tslib.pyx

+3
Original file line numberDiff line numberDiff line change
@@ -2340,6 +2340,7 @@ cdef extern from "period.h":
23402340

23412341
ctypedef int64_t (*freq_conv_func)(int64_t, char, asfreq_info*)
23422342

2343+
void initialize_daytime_conversion_factor_matrix()
23432344
int64_t asfreq(int64_t dtordinal, int freq1, int freq2, char relation) except INT32_MIN
23442345
freq_conv_func get_asfreq_func(int fromFreq, int toFreq)
23452346
void get_asfreq_info(int fromFreq, int toFreq, asfreq_info *af_info)
@@ -2368,6 +2369,8 @@ cdef extern from "period.h":
23682369
char *c_strftime(date_info *dinfo, char *fmt)
23692370
int get_yq(int64_t ordinal, int freq, int *quarter, int *year)
23702371

2372+
initialize_daytime_conversion_factor_matrix()
2373+
23712374
# Period logic
23722375
#----------------------------------------------------------------------
23732376

0 commit comments

Comments
 (0)