lightgbm_R.cpp 31.3 KB
Newer Older
1
2
3
4
/*!
 * Copyright (c) 2017 Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See LICENSE file in the project root for license information.
 */
5
6

#include "lightgbm_R.h"
Guolin Ke's avatar
Guolin Ke committed
7

8
9
10
11
12
13
14
#include <LightGBM/utils/common.h>
#include <LightGBM/utils/log.h>
#include <LightGBM/utils/openmp_wrapper.h>
#include <LightGBM/utils/text_reader.h>

#include <R_ext/Rdynload.h>

15
16
17
18
#define R_NO_REMAP
#define R_USE_C99_IN_CXX
#include <R_ext/Error.h>

19
20
21
22
23
24
25
#include <string>
#include <cstdio>
#include <cstring>
#include <memory>
#include <utility>
#include <vector>

Guolin Ke's avatar
Guolin Ke committed
26
27
#define COL_MAJOR (0)

28
29
30
31
32
33
#define MAX_LENGTH_ERR_MSG 1024
char R_errmsg_buffer[MAX_LENGTH_ERR_MSG];
struct LGBM_R_ErrorClass { SEXP cont_token; };
void LGBM_R_save_exception_msg(const std::exception &err);
void LGBM_R_save_exception_msg(const std::string &err);

Guolin Ke's avatar
Guolin Ke committed
34
35
36
#define R_API_BEGIN() \
  try {
#define R_API_END() } \
37
38
39
40
41
42
  catch(LGBM_R_ErrorClass &cont) { R_ContinueUnwind(cont.cont_token); } \
  catch(std::exception& ex) { LGBM_R_save_exception_msg(ex); } \
  catch(std::string& ex) { LGBM_R_save_exception_msg(ex); } \
  catch(...) { Rf_error("unknown exception"); } \
  Rf_error(R_errmsg_buffer); \
  return R_NilValue; /* <- won't be reached */
Guolin Ke's avatar
Guolin Ke committed
43
44
45

#define CHECK_CALL(x) \
  if ((x) != 0) { \
46
    throw std::runtime_error(LGBM_GetLastError()); \
Guolin Ke's avatar
Guolin Ke committed
47
48
  }

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// These are helper functions to allow doing a stack unwind
// after an R allocation error, which would trigger a long jump.
void LGBM_R_save_exception_msg(const std::exception &err) {
  std::snprintf(R_errmsg_buffer, MAX_LENGTH_ERR_MSG, "%s\n", err.what());
}

void LGBM_R_save_exception_msg(const std::string &err) {
  std::snprintf(R_errmsg_buffer, MAX_LENGTH_ERR_MSG, "%s\n", err.c_str());
}

SEXP wrapped_R_string(void *len) {
  return Rf_allocVector(STRSXP, *(reinterpret_cast<R_xlen_t*>(len)));
}

SEXP wrapped_Rf_mkChar(void *txt) {
  return Rf_mkChar(reinterpret_cast<char*>(txt));
}

void throw_R_memerr(void *ptr_cont_token, Rboolean jump) {
  if (jump) {
    LGBM_R_ErrorClass err{*(reinterpret_cast<SEXP*>(ptr_cont_token))};
    throw err;
  }
}

SEXP safe_R_string(R_xlen_t len, SEXP *cont_token) {
  return R_UnwindProtect(wrapped_R_string, reinterpret_cast<void*>(&len), throw_R_memerr, cont_token, *cont_token);
}

SEXP safe_R_mkChar(char *txt, SEXP *cont_token) {
  return R_UnwindProtect(wrapped_Rf_mkChar, reinterpret_cast<void*>(txt), throw_R_memerr, cont_token, *cont_token);
}

82
83
using LightGBM::Common::Split;
using LightGBM::Log;
Guolin Ke's avatar
Guolin Ke committed
84

85
86
87
88
SEXP LGBM_HandleIsNull_R(SEXP handle) {
  return Rf_ScalarLogical(R_ExternalPtrAddr(handle) == NULL);
}

89
90
91
92
void _DatasetFinalizer(SEXP handle) {
  LGBM_DatasetFree_R(handle);
}

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
void _AssertBoosterHandleNotNull(SEXP handle) {
  if (Rf_isNull(handle) || !R_ExternalPtrAddr(handle)) {
    Rf_error(
      "Attempting to use a Booster which no longer exists. "
      "This can happen if you have called Booster$finalize() or if this Booster was saved with saveRDS(). "
      "To avoid this error in the future, use saveRDS.lgb.Booster() or Booster$save_model() to save lightgbm Boosters.");
  }
}

void _AssertDatasetHandleNotNull(SEXP handle) {
  if (Rf_isNull(handle) || !R_ExternalPtrAddr(handle)) {
    Rf_error(
      "Attempting to use a Dataset which no longer exists. "
      "This can happen if you have called Dataset$finalize() or if this Dataset was saved with saveRDS(). "
      "To avoid this error in the future, use lgb.Dataset.save() or Dataset$save_binary() to save lightgbm Datasets.");
  }
}

111
112
SEXP LGBM_DatasetCreateFromFile_R(SEXP filename,
  SEXP parameters,
113
  SEXP reference) {
114
  R_API_BEGIN();
115
  SEXP ret = PROTECT(R_MakeExternalPtr(nullptr, R_NilValue, R_NilValue));
Guolin Ke's avatar
Guolin Ke committed
116
  DatasetHandle handle = nullptr;
117
118
119
120
  DatasetHandle ref = nullptr;
  if (!Rf_isNull(reference)) {
    ref = R_ExternalPtrAddr(reference);
  }
121
122
123
  const char* filename_ptr = CHAR(PROTECT(Rf_asChar(filename)));
  const char* parameters_ptr = CHAR(PROTECT(Rf_asChar(parameters)));
  CHECK_CALL(LGBM_DatasetCreateFromFile(filename_ptr, parameters_ptr, ref, &handle));
124
  R_SetExternalPtrAddr(ret, handle);
125
  R_RegisterCFinalizerEx(ret, _DatasetFinalizer, TRUE);
126
  UNPROTECT(3);
127
  return ret;
128
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
129
130
}

131
132
133
SEXP LGBM_DatasetCreateFromCSC_R(SEXP indptr,
  SEXP indices,
  SEXP data,
134
135
136
  SEXP num_indptr,
  SEXP nelem,
  SEXP num_row,
137
  SEXP parameters,
138
  SEXP reference) {
139
  R_API_BEGIN();
140
  SEXP ret = PROTECT(R_MakeExternalPtr(nullptr, R_NilValue, R_NilValue));
141
142
143
  const int* p_indptr = INTEGER(indptr);
  const int* p_indices = INTEGER(indices);
  const double* p_data = REAL(data);
144
145
146
  int64_t nindptr = static_cast<int64_t>(Rf_asInteger(num_indptr));
  int64_t ndata = static_cast<int64_t>(Rf_asInteger(nelem));
  int64_t nrow = static_cast<int64_t>(Rf_asInteger(num_row));
147
  const char* parameters_ptr = CHAR(PROTECT(Rf_asChar(parameters)));
Guolin Ke's avatar
Guolin Ke committed
148
  DatasetHandle handle = nullptr;
149
150
151
152
  DatasetHandle ref = nullptr;
  if (!Rf_isNull(reference)) {
    ref = R_ExternalPtrAddr(reference);
  }
Guolin Ke's avatar
Guolin Ke committed
153
154
  CHECK_CALL(LGBM_DatasetCreateFromCSC(p_indptr, C_API_DTYPE_INT32, p_indices,
    p_data, C_API_DTYPE_FLOAT64, nindptr, ndata,
155
    nrow, parameters_ptr, ref, &handle));
156
  R_SetExternalPtrAddr(ret, handle);
157
  R_RegisterCFinalizerEx(ret, _DatasetFinalizer, TRUE);
158
  UNPROTECT(2);
159
  return ret;
160
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
161
162
}

163
SEXP LGBM_DatasetCreateFromMat_R(SEXP data,
164
165
  SEXP num_row,
  SEXP num_col,
166
  SEXP parameters,
167
  SEXP reference) {
168
  R_API_BEGIN();
169
  SEXP ret = PROTECT(R_MakeExternalPtr(nullptr, R_NilValue, R_NilValue));
170
171
  int32_t nrow = static_cast<int32_t>(Rf_asInteger(num_row));
  int32_t ncol = static_cast<int32_t>(Rf_asInteger(num_col));
172
  double* p_mat = REAL(data);
173
  const char* parameters_ptr = CHAR(PROTECT(Rf_asChar(parameters)));
Guolin Ke's avatar
Guolin Ke committed
174
  DatasetHandle handle = nullptr;
175
176
177
178
  DatasetHandle ref = nullptr;
  if (!Rf_isNull(reference)) {
    ref = R_ExternalPtrAddr(reference);
  }
Guolin Ke's avatar
Guolin Ke committed
179
  CHECK_CALL(LGBM_DatasetCreateFromMat(p_mat, C_API_DTYPE_FLOAT64, nrow, ncol, COL_MAJOR,
180
    parameters_ptr, ref, &handle));
181
  R_SetExternalPtrAddr(ret, handle);
182
  R_RegisterCFinalizerEx(ret, _DatasetFinalizer, TRUE);
183
  UNPROTECT(2);
184
  return ret;
185
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
186
187
}

188
SEXP LGBM_DatasetGetSubset_R(SEXP handle,
189
  SEXP used_row_indices,
190
  SEXP len_used_row_indices,
191
  SEXP parameters) {
192
  R_API_BEGIN();
193
  _AssertDatasetHandleNotNull(handle);
194
  SEXP ret = PROTECT(R_MakeExternalPtr(nullptr, R_NilValue, R_NilValue));
195
196
  int32_t len = static_cast<int32_t>(Rf_asInteger(len_used_row_indices));
  std::vector<int32_t> idxvec(len);
197
  // convert from one-based to zero-based index
Guolin Ke's avatar
Guolin Ke committed
198
#pragma omp parallel for schedule(static, 512) if (len >= 1024)
199
200
  for (int32_t i = 0; i < len; ++i) {
    idxvec[i] = static_cast<int32_t>(INTEGER(used_row_indices)[i] - 1);
Guolin Ke's avatar
Guolin Ke committed
201
  }
202
  const char* parameters_ptr = CHAR(PROTECT(Rf_asChar(parameters)));
Guolin Ke's avatar
Guolin Ke committed
203
  DatasetHandle res = nullptr;
204
  CHECK_CALL(LGBM_DatasetGetSubset(R_ExternalPtrAddr(handle),
205
    idxvec.data(), len, parameters_ptr,
Guolin Ke's avatar
Guolin Ke committed
206
    &res));
207
  R_SetExternalPtrAddr(ret, res);
208
  R_RegisterCFinalizerEx(ret, _DatasetFinalizer, TRUE);
209
  UNPROTECT(2);
210
  return ret;
211
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
212
213
}

214
SEXP LGBM_DatasetSetFeatureNames_R(SEXP handle,
215
  SEXP feature_names) {
216
  R_API_BEGIN();
217
  _AssertDatasetHandleNotNull(handle);
218
  auto vec_names = Split(CHAR(PROTECT(Rf_asChar(feature_names))), '\t');
Guolin Ke's avatar
Guolin Ke committed
219
220
221
222
223
  std::vector<const char*> vec_sptr;
  int len = static_cast<int>(vec_names.size());
  for (int i = 0; i < len; ++i) {
    vec_sptr.push_back(vec_names[i].c_str());
  }
224
  CHECK_CALL(LGBM_DatasetSetFeatureNames(R_ExternalPtrAddr(handle),
Guolin Ke's avatar
Guolin Ke committed
225
    vec_sptr.data(), len));
226
227
  UNPROTECT(1);
  return R_NilValue;
228
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
229
230
}

231
SEXP LGBM_DatasetGetFeatureNames_R(SEXP handle) {
232
233
  SEXP cont_token = PROTECT(R_MakeUnwindCont());
  R_API_BEGIN();
234
  _AssertDatasetHandleNotNull(handle);
235
  SEXP feature_names;
Guolin Ke's avatar
Guolin Ke committed
236
  int len = 0;
237
  CHECK_CALL(LGBM_DatasetGetNumFeature(R_ExternalPtrAddr(handle), &len));
238
  const size_t reserved_string_size = 256;
Guolin Ke's avatar
Guolin Ke committed
239
240
241
  std::vector<std::vector<char>> names(len);
  std::vector<char*> ptr_names(len);
  for (int i = 0; i < len; ++i) {
242
    names[i].resize(reserved_string_size);
Guolin Ke's avatar
Guolin Ke committed
243
244
245
    ptr_names[i] = names[i].data();
  }
  int out_len;
246
247
248
  size_t required_string_size;
  CHECK_CALL(
    LGBM_DatasetGetFeatureNames(
249
      R_ExternalPtrAddr(handle),
250
251
252
      len, &out_len,
      reserved_string_size, &required_string_size,
      ptr_names.data()));
253
254
255
256
257
258
259
260
261
  // if any feature names were larger than allocated size,
  // allow for a larger size and try again
  if (required_string_size > reserved_string_size) {
    for (int i = 0; i < len; ++i) {
      names[i].resize(required_string_size);
      ptr_names[i] = names[i].data();
    }
    CHECK_CALL(
      LGBM_DatasetGetFeatureNames(
262
        R_ExternalPtrAddr(handle),
263
264
265
266
267
268
        len,
        &out_len,
        required_string_size,
        &required_string_size,
        ptr_names.data()));
  }
Nikita Titov's avatar
Nikita Titov committed
269
  CHECK_EQ(len, out_len);
270
  feature_names = PROTECT(safe_R_string(static_cast<R_xlen_t>(len), &cont_token));
271
  for (int i = 0; i < len; ++i) {
272
    SET_STRING_ELT(feature_names, i, safe_R_mkChar(ptr_names[i], &cont_token));
273
  }
274
  UNPROTECT(2);
275
  return feature_names;
276
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
277
278
}

279
SEXP LGBM_DatasetSaveBinary_R(SEXP handle,
280
  SEXP filename) {
Guolin Ke's avatar
Guolin Ke committed
281
  R_API_BEGIN();
282
  _AssertDatasetHandleNotNull(handle);
283
  const char* filename_ptr = CHAR(PROTECT(Rf_asChar(filename)));
284
  CHECK_CALL(LGBM_DatasetSaveBinary(R_ExternalPtrAddr(handle),
285
286
287
    filename_ptr));
  UNPROTECT(1);
  return R_NilValue;
288
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
289
290
}

291
SEXP LGBM_DatasetFree_R(SEXP handle) {
Guolin Ke's avatar
Guolin Ke committed
292
  R_API_BEGIN();
293
  if (!Rf_isNull(handle) && R_ExternalPtrAddr(handle)) {
294
295
    CHECK_CALL(LGBM_DatasetFree(R_ExternalPtrAddr(handle)));
    R_ClearExternalPtr(handle);
Guolin Ke's avatar
Guolin Ke committed
296
  }
297
  return R_NilValue;
298
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
299
300
}

301
SEXP LGBM_DatasetSetField_R(SEXP handle,
302
  SEXP field_name,
303
  SEXP field_data,
304
  SEXP num_element) {
305
  R_API_BEGIN();
306
  _AssertDatasetHandleNotNull(handle);
307
  int len = Rf_asInteger(num_element);
308
  const char* name = CHAR(PROTECT(Rf_asChar(field_name)));
Guolin Ke's avatar
Guolin Ke committed
309
310
  if (!strcmp("group", name) || !strcmp("query", name)) {
    std::vector<int32_t> vec(len);
Guolin Ke's avatar
Guolin Ke committed
311
#pragma omp parallel for schedule(static, 512) if (len >= 1024)
Guolin Ke's avatar
Guolin Ke committed
312
    for (int i = 0; i < len; ++i) {
313
      vec[i] = static_cast<int32_t>(INTEGER(field_data)[i]);
Guolin Ke's avatar
Guolin Ke committed
314
    }
315
    CHECK_CALL(LGBM_DatasetSetField(R_ExternalPtrAddr(handle), name, vec.data(), len, C_API_DTYPE_INT32));
316
  } else if (!strcmp("init_score", name)) {
317
    CHECK_CALL(LGBM_DatasetSetField(R_ExternalPtrAddr(handle), name, REAL(field_data), len, C_API_DTYPE_FLOAT64));
Guolin Ke's avatar
Guolin Ke committed
318
319
  } else {
    std::vector<float> vec(len);
Guolin Ke's avatar
Guolin Ke committed
320
#pragma omp parallel for schedule(static, 512) if (len >= 1024)
Guolin Ke's avatar
Guolin Ke committed
321
    for (int i = 0; i < len; ++i) {
322
      vec[i] = static_cast<float>(REAL(field_data)[i]);
Guolin Ke's avatar
Guolin Ke committed
323
    }
324
    CHECK_CALL(LGBM_DatasetSetField(R_ExternalPtrAddr(handle), name, vec.data(), len, C_API_DTYPE_FLOAT32));
Guolin Ke's avatar
Guolin Ke committed
325
  }
326
327
  UNPROTECT(1);
  return R_NilValue;
328
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
329
330
}

331
SEXP LGBM_DatasetGetField_R(SEXP handle,
332
  SEXP field_name,
333
  SEXP field_data) {
334
  R_API_BEGIN();
335
  _AssertDatasetHandleNotNull(handle);
336
  const char* name = CHAR(PROTECT(Rf_asChar(field_name)));
Guolin Ke's avatar
Guolin Ke committed
337
338
339
  int out_len = 0;
  int out_type = 0;
  const void* res;
340
  CHECK_CALL(LGBM_DatasetGetField(R_ExternalPtrAddr(handle), name, &out_len, &res, &out_type));
Guolin Ke's avatar
Guolin Ke committed
341
342
343
  if (!strcmp("group", name) || !strcmp("query", name)) {
    auto p_data = reinterpret_cast<const int32_t*>(res);
    // convert from boundaries to size
Guolin Ke's avatar
Guolin Ke committed
344
#pragma omp parallel for schedule(static, 512) if (out_len >= 1024)
Guolin Ke's avatar
Guolin Ke committed
345
    for (int i = 0; i < out_len - 1; ++i) {
346
      INTEGER(field_data)[i] = p_data[i + 1] - p_data[i];
Guolin Ke's avatar
Guolin Ke committed
347
    }
Guolin Ke's avatar
Guolin Ke committed
348
349
  } else if (!strcmp("init_score", name)) {
    auto p_data = reinterpret_cast<const double*>(res);
Guolin Ke's avatar
Guolin Ke committed
350
#pragma omp parallel for schedule(static, 512) if (out_len >= 1024)
Guolin Ke's avatar
Guolin Ke committed
351
    for (int i = 0; i < out_len; ++i) {
352
      REAL(field_data)[i] = p_data[i];
Guolin Ke's avatar
Guolin Ke committed
353
    }
Guolin Ke's avatar
Guolin Ke committed
354
355
  } else {
    auto p_data = reinterpret_cast<const float*>(res);
Guolin Ke's avatar
Guolin Ke committed
356
#pragma omp parallel for schedule(static, 512) if (out_len >= 1024)
Guolin Ke's avatar
Guolin Ke committed
357
    for (int i = 0; i < out_len; ++i) {
358
      REAL(field_data)[i] = p_data[i];
Guolin Ke's avatar
Guolin Ke committed
359
360
    }
  }
361
362
  UNPROTECT(1);
  return R_NilValue;
363
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
364
365
}

366
SEXP LGBM_DatasetGetFieldSize_R(SEXP handle,
367
  SEXP field_name,
368
  SEXP out) {
369
  R_API_BEGIN();
370
  _AssertDatasetHandleNotNull(handle);
371
  const char* name = CHAR(PROTECT(Rf_asChar(field_name)));
Guolin Ke's avatar
Guolin Ke committed
372
373
374
  int out_len = 0;
  int out_type = 0;
  const void* res;
375
  CHECK_CALL(LGBM_DatasetGetField(R_ExternalPtrAddr(handle), name, &out_len, &res, &out_type));
Guolin Ke's avatar
Guolin Ke committed
376
377
378
  if (!strcmp("group", name) || !strcmp("query", name)) {
    out_len -= 1;
  }
379
  INTEGER(out)[0] = out_len;
380
381
  UNPROTECT(1);
  return R_NilValue;
382
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
383
384
}

385
386
SEXP LGBM_DatasetUpdateParamChecking_R(SEXP old_params,
  SEXP new_params) {
387
  R_API_BEGIN();
388
389
390
391
392
  const char* old_params_ptr = CHAR(PROTECT(Rf_asChar(old_params)));
  const char* new_params_ptr = CHAR(PROTECT(Rf_asChar(new_params)));
  CHECK_CALL(LGBM_DatasetUpdateParamChecking(old_params_ptr, new_params_ptr));
  UNPROTECT(2);
  return R_NilValue;
393
  R_API_END();
394
395
}

396
SEXP LGBM_DatasetGetNumData_R(SEXP handle, SEXP out) {
Guolin Ke's avatar
Guolin Ke committed
397
  R_API_BEGIN();
398
  _AssertDatasetHandleNotNull(handle);
399
  int nrow;
400
  CHECK_CALL(LGBM_DatasetGetNumData(R_ExternalPtrAddr(handle), &nrow));
401
  INTEGER(out)[0] = nrow;
402
  return R_NilValue;
403
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
404
405
}

406
SEXP LGBM_DatasetGetNumFeature_R(SEXP handle,
407
  SEXP out) {
Guolin Ke's avatar
Guolin Ke committed
408
  R_API_BEGIN();
409
  _AssertDatasetHandleNotNull(handle);
410
  int nfeature;
411
  CHECK_CALL(LGBM_DatasetGetNumFeature(R_ExternalPtrAddr(handle), &nfeature));
412
  INTEGER(out)[0] = nfeature;
413
  return R_NilValue;
414
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
415
416
417
418
}

// --- start Booster interfaces

419
420
421
422
void _BoosterFinalizer(SEXP handle) {
  LGBM_BoosterFree_R(handle);
}

423
SEXP LGBM_BoosterFree_R(SEXP handle) {
Guolin Ke's avatar
Guolin Ke committed
424
  R_API_BEGIN();
425
  if (!Rf_isNull(handle) && R_ExternalPtrAddr(handle)) {
426
427
    CHECK_CALL(LGBM_BoosterFree(R_ExternalPtrAddr(handle)));
    R_ClearExternalPtr(handle);
Guolin Ke's avatar
Guolin Ke committed
428
  }
429
  return R_NilValue;
430
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
431
432
}

433
434
SEXP LGBM_BoosterCreate_R(SEXP train_data,
  SEXP parameters) {
435
  R_API_BEGIN();
436
  _AssertDatasetHandleNotNull(train_data);
437
  SEXP ret = PROTECT(R_MakeExternalPtr(nullptr, R_NilValue, R_NilValue));
438
  const char* parameters_ptr = CHAR(PROTECT(Rf_asChar(parameters)));
Guolin Ke's avatar
Guolin Ke committed
439
  BoosterHandle handle = nullptr;
440
  CHECK_CALL(LGBM_BoosterCreate(R_ExternalPtrAddr(train_data), parameters_ptr, &handle));
441
  R_SetExternalPtrAddr(ret, handle);
442
  R_RegisterCFinalizerEx(ret, _BoosterFinalizer, TRUE);
443
  UNPROTECT(2);
444
  return ret;
445
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
446
447
}

448
SEXP LGBM_BoosterCreateFromModelfile_R(SEXP filename) {
449
  R_API_BEGIN();
450
  SEXP ret = PROTECT(R_MakeExternalPtr(nullptr, R_NilValue, R_NilValue));
Guolin Ke's avatar
Guolin Ke committed
451
  int out_num_iterations = 0;
452
  const char* filename_ptr = CHAR(PROTECT(Rf_asChar(filename)));
Guolin Ke's avatar
Guolin Ke committed
453
  BoosterHandle handle = nullptr;
454
  CHECK_CALL(LGBM_BoosterCreateFromModelfile(filename_ptr, &out_num_iterations, &handle));
455
  R_SetExternalPtrAddr(ret, handle);
456
  R_RegisterCFinalizerEx(ret, _BoosterFinalizer, TRUE);
457
  UNPROTECT(2);
458
  return ret;
459
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
460
461
}

462
SEXP LGBM_BoosterLoadModelFromString_R(SEXP model_str) {
463
  R_API_BEGIN();
464
  SEXP ret = PROTECT(R_MakeExternalPtr(nullptr, R_NilValue, R_NilValue));
465
  int out_num_iterations = 0;
466
  const char* model_str_ptr = CHAR(PROTECT(Rf_asChar(model_str)));
Guolin Ke's avatar
Guolin Ke committed
467
  BoosterHandle handle = nullptr;
468
  CHECK_CALL(LGBM_BoosterLoadModelFromString(model_str_ptr, &out_num_iterations, &handle));
469
  R_SetExternalPtrAddr(ret, handle);
470
  R_RegisterCFinalizerEx(ret, _BoosterFinalizer, TRUE);
471
  UNPROTECT(2);
472
  return ret;
473
  R_API_END();
474
475
}

476
477
SEXP LGBM_BoosterMerge_R(SEXP handle,
  SEXP other_handle) {
Guolin Ke's avatar
Guolin Ke committed
478
  R_API_BEGIN();
479
480
  _AssertBoosterHandleNotNull(handle);
  _AssertBoosterHandleNotNull(other_handle);
481
  CHECK_CALL(LGBM_BoosterMerge(R_ExternalPtrAddr(handle), R_ExternalPtrAddr(other_handle)));
482
  return R_NilValue;
483
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
484
485
}

486
487
SEXP LGBM_BoosterAddValidData_R(SEXP handle,
  SEXP valid_data) {
Guolin Ke's avatar
Guolin Ke committed
488
  R_API_BEGIN();
489
490
  _AssertBoosterHandleNotNull(handle);
  _AssertDatasetHandleNotNull(valid_data);
491
  CHECK_CALL(LGBM_BoosterAddValidData(R_ExternalPtrAddr(handle), R_ExternalPtrAddr(valid_data)));
492
  return R_NilValue;
493
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
494
495
}

496
497
SEXP LGBM_BoosterResetTrainingData_R(SEXP handle,
  SEXP train_data) {
Guolin Ke's avatar
Guolin Ke committed
498
  R_API_BEGIN();
499
500
  _AssertBoosterHandleNotNull(handle);
  _AssertDatasetHandleNotNull(train_data);
501
  CHECK_CALL(LGBM_BoosterResetTrainingData(R_ExternalPtrAddr(handle), R_ExternalPtrAddr(train_data)));
502
  return R_NilValue;
503
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
504
505
}

506
SEXP LGBM_BoosterResetParameter_R(SEXP handle,
507
  SEXP parameters) {
Guolin Ke's avatar
Guolin Ke committed
508
  R_API_BEGIN();
509
  _AssertBoosterHandleNotNull(handle);
510
  const char* parameters_ptr = CHAR(PROTECT(Rf_asChar(parameters)));
511
512
513
  CHECK_CALL(LGBM_BoosterResetParameter(R_ExternalPtrAddr(handle), parameters_ptr));
  UNPROTECT(1);
  return R_NilValue;
514
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
515
516
}

517
SEXP LGBM_BoosterGetNumClasses_R(SEXP handle,
518
  SEXP out) {
Guolin Ke's avatar
Guolin Ke committed
519
  R_API_BEGIN();
520
  _AssertBoosterHandleNotNull(handle);
521
  int num_class;
522
  CHECK_CALL(LGBM_BoosterGetNumClasses(R_ExternalPtrAddr(handle), &num_class));
523
  INTEGER(out)[0] = num_class;
524
  return R_NilValue;
525
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
526
527
}

528
SEXP LGBM_BoosterUpdateOneIter_R(SEXP handle) {
Guolin Ke's avatar
Guolin Ke committed
529
  R_API_BEGIN();
530
  _AssertBoosterHandleNotNull(handle);
531
  int is_finished = 0;
532
  CHECK_CALL(LGBM_BoosterUpdateOneIter(R_ExternalPtrAddr(handle), &is_finished));
533
  return R_NilValue;
534
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
535
536
}

537
SEXP LGBM_BoosterUpdateOneIterCustom_R(SEXP handle,
538
539
  SEXP grad,
  SEXP hess,
540
  SEXP len) {
Guolin Ke's avatar
Guolin Ke committed
541
  R_API_BEGIN();
542
  _AssertBoosterHandleNotNull(handle);
543
  int is_finished = 0;
544
  int int_len = Rf_asInteger(len);
Guolin Ke's avatar
Guolin Ke committed
545
  std::vector<float> tgrad(int_len), thess(int_len);
Guolin Ke's avatar
Guolin Ke committed
546
#pragma omp parallel for schedule(static, 512) if (int_len >= 1024)
Guolin Ke's avatar
Guolin Ke committed
547
  for (int j = 0; j < int_len; ++j) {
548
549
    tgrad[j] = static_cast<float>(REAL(grad)[j]);
    thess[j] = static_cast<float>(REAL(hess)[j]);
Guolin Ke's avatar
Guolin Ke committed
550
  }
551
  CHECK_CALL(LGBM_BoosterUpdateOneIterCustom(R_ExternalPtrAddr(handle), tgrad.data(), thess.data(), &is_finished));
552
  return R_NilValue;
553
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
554
555
}

556
SEXP LGBM_BoosterRollbackOneIter_R(SEXP handle) {
Guolin Ke's avatar
Guolin Ke committed
557
  R_API_BEGIN();
558
  _AssertBoosterHandleNotNull(handle);
559
  CHECK_CALL(LGBM_BoosterRollbackOneIter(R_ExternalPtrAddr(handle)));
560
  return R_NilValue;
561
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
562
563
}

564
SEXP LGBM_BoosterGetCurrentIteration_R(SEXP handle,
565
  SEXP out) {
Guolin Ke's avatar
Guolin Ke committed
566
  R_API_BEGIN();
567
  _AssertBoosterHandleNotNull(handle);
568
  int out_iteration;
569
  CHECK_CALL(LGBM_BoosterGetCurrentIteration(R_ExternalPtrAddr(handle), &out_iteration));
570
  INTEGER(out)[0] = out_iteration;
571
  return R_NilValue;
572
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
573
574
}

575
SEXP LGBM_BoosterGetUpperBoundValue_R(SEXP handle,
576
  SEXP out_result) {
577
  R_API_BEGIN();
578
  _AssertBoosterHandleNotNull(handle);
579
  double* ptr_ret = REAL(out_result);
580
  CHECK_CALL(LGBM_BoosterGetUpperBoundValue(R_ExternalPtrAddr(handle), ptr_ret));
581
  return R_NilValue;
582
  R_API_END();
583
584
}

585
SEXP LGBM_BoosterGetLowerBoundValue_R(SEXP handle,
586
  SEXP out_result) {
587
  R_API_BEGIN();
588
  _AssertBoosterHandleNotNull(handle);
589
  double* ptr_ret = REAL(out_result);
590
  CHECK_CALL(LGBM_BoosterGetLowerBoundValue(R_ExternalPtrAddr(handle), ptr_ret));
591
  return R_NilValue;
592
  R_API_END();
593
594
}

595
SEXP LGBM_BoosterGetEvalNames_R(SEXP handle) {
596
597
  SEXP cont_token = PROTECT(R_MakeUnwindCont());
  R_API_BEGIN();
598
  _AssertBoosterHandleNotNull(handle);
599
  SEXP eval_names;
Guolin Ke's avatar
Guolin Ke committed
600
  int len;
601
  CHECK_CALL(LGBM_BoosterGetEvalCounts(R_ExternalPtrAddr(handle), &len));
602
  const size_t reserved_string_size = 128;
Guolin Ke's avatar
Guolin Ke committed
603
604
605
  std::vector<std::vector<char>> names(len);
  std::vector<char*> ptr_names(len);
  for (int i = 0; i < len; ++i) {
606
    names[i].resize(reserved_string_size);
Guolin Ke's avatar
Guolin Ke committed
607
608
    ptr_names[i] = names[i].data();
  }
609

Guolin Ke's avatar
Guolin Ke committed
610
  int out_len;
611
612
613
  size_t required_string_size;
  CHECK_CALL(
    LGBM_BoosterGetEvalNames(
614
      R_ExternalPtrAddr(handle),
615
616
617
      len, &out_len,
      reserved_string_size, &required_string_size,
      ptr_names.data()));
618
619
620
621
622
623
624
625
626
  // if any eval names were larger than allocated size,
  // allow for a larger size and try again
  if (required_string_size > reserved_string_size) {
    for (int i = 0; i < len; ++i) {
      names[i].resize(required_string_size);
      ptr_names[i] = names[i].data();
    }
    CHECK_CALL(
      LGBM_BoosterGetEvalNames(
627
        R_ExternalPtrAddr(handle),
628
629
630
631
632
633
        len,
        &out_len,
        required_string_size,
        &required_string_size,
        ptr_names.data()));
  }
Nikita Titov's avatar
Nikita Titov committed
634
  CHECK_EQ(out_len, len);
635
  eval_names = PROTECT(safe_R_string(static_cast<R_xlen_t>(len), &cont_token));
636
  for (int i = 0; i < len; ++i) {
637
    SET_STRING_ELT(eval_names, i, safe_R_mkChar(ptr_names[i], &cont_token));
638
  }
639
  UNPROTECT(2);
640
  return eval_names;
641
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
642
643
}

644
SEXP LGBM_BoosterGetEval_R(SEXP handle,
645
  SEXP data_idx,
646
  SEXP out_result) {
Guolin Ke's avatar
Guolin Ke committed
647
  R_API_BEGIN();
648
  _AssertBoosterHandleNotNull(handle);
Guolin Ke's avatar
Guolin Ke committed
649
  int len;
650
  CHECK_CALL(LGBM_BoosterGetEvalCounts(R_ExternalPtrAddr(handle), &len));
651
  double* ptr_ret = REAL(out_result);
Guolin Ke's avatar
Guolin Ke committed
652
  int out_len;
653
  CHECK_CALL(LGBM_BoosterGetEval(R_ExternalPtrAddr(handle), Rf_asInteger(data_idx), &out_len, ptr_ret));
Nikita Titov's avatar
Nikita Titov committed
654
  CHECK_EQ(out_len, len);
655
  return R_NilValue;
656
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
657
658
}

659
SEXP LGBM_BoosterGetNumPredict_R(SEXP handle,
660
  SEXP data_idx,
661
  SEXP out) {
Guolin Ke's avatar
Guolin Ke committed
662
  R_API_BEGIN();
663
  _AssertBoosterHandleNotNull(handle);
Guolin Ke's avatar
Guolin Ke committed
664
  int64_t len;
665
  CHECK_CALL(LGBM_BoosterGetNumPredict(R_ExternalPtrAddr(handle), Rf_asInteger(data_idx), &len));
666
  INTEGER(out)[0] = static_cast<int>(len);
667
  return R_NilValue;
668
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
669
670
}

671
SEXP LGBM_BoosterGetPredict_R(SEXP handle,
672
  SEXP data_idx,
673
  SEXP out_result) {
Guolin Ke's avatar
Guolin Ke committed
674
  R_API_BEGIN();
675
  _AssertBoosterHandleNotNull(handle);
676
  double* ptr_ret = REAL(out_result);
Guolin Ke's avatar
Guolin Ke committed
677
  int64_t out_len;
678
  CHECK_CALL(LGBM_BoosterGetPredict(R_ExternalPtrAddr(handle), Rf_asInteger(data_idx), &out_len, ptr_ret));
679
  return R_NilValue;
680
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
681
682
}

683
int GetPredictType(SEXP is_rawscore, SEXP is_leafidx, SEXP is_predcontrib) {
Guolin Ke's avatar
Guolin Ke committed
684
  int pred_type = C_API_PREDICT_NORMAL;
685
  if (Rf_asInteger(is_rawscore)) {
Guolin Ke's avatar
Guolin Ke committed
686
687
    pred_type = C_API_PREDICT_RAW_SCORE;
  }
688
  if (Rf_asInteger(is_leafidx)) {
Guolin Ke's avatar
Guolin Ke committed
689
690
    pred_type = C_API_PREDICT_LEAF_INDEX;
  }
691
  if (Rf_asInteger(is_predcontrib)) {
692
693
    pred_type = C_API_PREDICT_CONTRIB;
  }
Guolin Ke's avatar
Guolin Ke committed
694
695
696
  return pred_type;
}

697
SEXP LGBM_BoosterPredictForFile_R(SEXP handle,
698
  SEXP data_filename,
699
700
701
702
703
704
  SEXP data_has_header,
  SEXP is_rawscore,
  SEXP is_leafidx,
  SEXP is_predcontrib,
  SEXP start_iteration,
  SEXP num_iteration,
705
706
  SEXP parameter,
  SEXP result_filename) {
707
  R_API_BEGIN();
708
  _AssertBoosterHandleNotNull(handle);
709
710
711
  const char* data_filename_ptr = CHAR(PROTECT(Rf_asChar(data_filename)));
  const char* parameter_ptr = CHAR(PROTECT(Rf_asChar(parameter)));
  const char* result_filename_ptr = CHAR(PROTECT(Rf_asChar(result_filename)));
712
  int pred_type = GetPredictType(is_rawscore, is_leafidx, is_predcontrib);
713
714
715
716
717
  CHECK_CALL(LGBM_BoosterPredictForFile(R_ExternalPtrAddr(handle), data_filename_ptr,
    Rf_asInteger(data_has_header), pred_type, Rf_asInteger(start_iteration), Rf_asInteger(num_iteration), parameter_ptr,
    result_filename_ptr));
  UNPROTECT(3);
  return R_NilValue;
718
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
719
720
}

721
SEXP LGBM_BoosterCalcNumPredict_R(SEXP handle,
722
723
724
725
726
727
  SEXP num_row,
  SEXP is_rawscore,
  SEXP is_leafidx,
  SEXP is_predcontrib,
  SEXP start_iteration,
  SEXP num_iteration,
728
  SEXP out_len) {
Guolin Ke's avatar
Guolin Ke committed
729
  R_API_BEGIN();
730
  _AssertBoosterHandleNotNull(handle);
731
  int pred_type = GetPredictType(is_rawscore, is_leafidx, is_predcontrib);
Guolin Ke's avatar
Guolin Ke committed
732
  int64_t len = 0;
733
  CHECK_CALL(LGBM_BoosterCalcNumPredict(R_ExternalPtrAddr(handle), Rf_asInteger(num_row),
734
    pred_type, Rf_asInteger(start_iteration), Rf_asInteger(num_iteration), &len));
735
  INTEGER(out_len)[0] = static_cast<int>(len);
736
  return R_NilValue;
737
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
738
739
}

740
SEXP LGBM_BoosterPredictForCSC_R(SEXP handle,
741
742
743
  SEXP indptr,
  SEXP indices,
  SEXP data,
744
745
746
747
748
749
750
751
  SEXP num_indptr,
  SEXP nelem,
  SEXP num_row,
  SEXP is_rawscore,
  SEXP is_leafidx,
  SEXP is_predcontrib,
  SEXP start_iteration,
  SEXP num_iteration,
752
  SEXP parameter,
753
  SEXP out_result) {
754
  R_API_BEGIN();
755
  _AssertBoosterHandleNotNull(handle);
756
  int pred_type = GetPredictType(is_rawscore, is_leafidx, is_predcontrib);
757
  const int* p_indptr = INTEGER(indptr);
758
  const int32_t* p_indices = reinterpret_cast<const int32_t*>(INTEGER(indices));
759
  const double* p_data = REAL(data);
760
761
762
  int64_t nindptr = static_cast<int64_t>(Rf_asInteger(num_indptr));
  int64_t ndata = static_cast<int64_t>(Rf_asInteger(nelem));
  int64_t nrow = static_cast<int64_t>(Rf_asInteger(num_row));
763
  double* ptr_ret = REAL(out_result);
Guolin Ke's avatar
Guolin Ke committed
764
  int64_t out_len;
765
  const char* parameter_ptr = CHAR(PROTECT(Rf_asChar(parameter)));
766
  CHECK_CALL(LGBM_BoosterPredictForCSC(R_ExternalPtrAddr(handle),
Guolin Ke's avatar
Guolin Ke committed
767
768
    p_indptr, C_API_DTYPE_INT32, p_indices,
    p_data, C_API_DTYPE_FLOAT64, nindptr, ndata,
769
770
771
    nrow, pred_type, Rf_asInteger(start_iteration), Rf_asInteger(num_iteration), parameter_ptr, &out_len, ptr_ret));
  UNPROTECT(1);
  return R_NilValue;
772
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
773
774
}

775
SEXP LGBM_BoosterPredictForMat_R(SEXP handle,
776
  SEXP data,
777
778
779
780
781
782
783
  SEXP num_row,
  SEXP num_col,
  SEXP is_rawscore,
  SEXP is_leafidx,
  SEXP is_predcontrib,
  SEXP start_iteration,
  SEXP num_iteration,
784
  SEXP parameter,
785
  SEXP out_result) {
786
  R_API_BEGIN();
787
  _AssertBoosterHandleNotNull(handle);
788
  int pred_type = GetPredictType(is_rawscore, is_leafidx, is_predcontrib);
789
790
  int32_t nrow = static_cast<int32_t>(Rf_asInteger(num_row));
  int32_t ncol = static_cast<int32_t>(Rf_asInteger(num_col));
791
792
  const double* p_mat = REAL(data);
  double* ptr_ret = REAL(out_result);
793
  const char* parameter_ptr = CHAR(PROTECT(Rf_asChar(parameter)));
Guolin Ke's avatar
Guolin Ke committed
794
  int64_t out_len;
795
  CHECK_CALL(LGBM_BoosterPredictForMat(R_ExternalPtrAddr(handle),
Guolin Ke's avatar
Guolin Ke committed
796
    p_mat, C_API_DTYPE_FLOAT64, nrow, ncol, COL_MAJOR,
797
798
799
    pred_type, Rf_asInteger(start_iteration), Rf_asInteger(num_iteration), parameter_ptr, &out_len, ptr_ret));
  UNPROTECT(1);
  return R_NilValue;
800
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
801
802
}

803
SEXP LGBM_BoosterSaveModel_R(SEXP handle,
804
805
  SEXP num_iteration,
  SEXP feature_importance_type,
806
  SEXP filename) {
Guolin Ke's avatar
Guolin Ke committed
807
  R_API_BEGIN();
808
  _AssertBoosterHandleNotNull(handle);
809
  const char* filename_ptr = CHAR(PROTECT(Rf_asChar(filename)));
810
811
812
  CHECK_CALL(LGBM_BoosterSaveModel(R_ExternalPtrAddr(handle), 0, Rf_asInteger(num_iteration), Rf_asInteger(feature_importance_type), filename_ptr));
  UNPROTECT(1);
  return R_NilValue;
813
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
814
815
}

816
SEXP LGBM_BoosterSaveModelToString_R(SEXP handle,
817
  SEXP num_iteration,
818
  SEXP feature_importance_type) {
819
820
  SEXP cont_token = PROTECT(R_MakeUnwindCont());
  R_API_BEGIN();
821
  _AssertBoosterHandleNotNull(handle);
822
  SEXP model_str;
823
  int64_t out_len = 0;
824
  int64_t buf_len = 1024 * 1024;
825
826
  int num_iter = Rf_asInteger(num_iteration);
  int importance_type = Rf_asInteger(feature_importance_type);
827
  std::vector<char> inner_char_buf(buf_len);
828
  CHECK_CALL(LGBM_BoosterSaveModelToString(R_ExternalPtrAddr(handle), 0, num_iter, importance_type, buf_len, &out_len, inner_char_buf.data()));
829
830
831
  // if the model string was larger than the initial buffer, allocate a bigger buffer and try again
  if (out_len > buf_len) {
    inner_char_buf.resize(out_len);
832
    CHECK_CALL(LGBM_BoosterSaveModelToString(R_ExternalPtrAddr(handle), 0, num_iter, importance_type, out_len, &out_len, inner_char_buf.data()));
833
  }
834
835
836
  model_str = PROTECT(safe_R_string(static_cast<R_xlen_t>(1), &cont_token));
  SET_STRING_ELT(model_str, 0, safe_R_mkChar(inner_char_buf.data(), &cont_token));
  UNPROTECT(2);
837
  return model_str;
838
  R_API_END();
839
840
}

841
SEXP LGBM_BoosterDumpModel_R(SEXP handle,
842
  SEXP num_iteration,
843
  SEXP feature_importance_type) {
844
845
  SEXP cont_token = PROTECT(R_MakeUnwindCont());
  R_API_BEGIN();
846
  _AssertBoosterHandleNotNull(handle);
847
  SEXP model_str;
848
  int64_t out_len = 0;
849
  int64_t buf_len = 1024 * 1024;
850
851
  int num_iter = Rf_asInteger(num_iteration);
  int importance_type = Rf_asInteger(feature_importance_type);
852
  std::vector<char> inner_char_buf(buf_len);
853
  CHECK_CALL(LGBM_BoosterDumpModel(R_ExternalPtrAddr(handle), 0, num_iter, importance_type, buf_len, &out_len, inner_char_buf.data()));
854
855
856
  // if the model string was larger than the initial buffer, allocate a bigger buffer and try again
  if (out_len > buf_len) {
    inner_char_buf.resize(out_len);
857
    CHECK_CALL(LGBM_BoosterDumpModel(R_ExternalPtrAddr(handle), 0, num_iter, importance_type, out_len, &out_len, inner_char_buf.data()));
858
  }
859
860
861
  model_str = PROTECT(safe_R_string(static_cast<R_xlen_t>(1), &cont_token));
  SET_STRING_ELT(model_str, 0, safe_R_mkChar(inner_char_buf.data(), &cont_token));
  UNPROTECT(2);
862
  return model_str;
863
  R_API_END();
Guolin Ke's avatar
Guolin Ke committed
864
}
865
866
867

// .Call() calls
static const R_CallMethodDef CallEntries[] = {
868
869
870
871
872
  {"LGBM_HandleIsNull_R"              , (DL_FUNC) &LGBM_HandleIsNull_R              , 1},
  {"LGBM_DatasetCreateFromFile_R"     , (DL_FUNC) &LGBM_DatasetCreateFromFile_R     , 3},
  {"LGBM_DatasetCreateFromCSC_R"      , (DL_FUNC) &LGBM_DatasetCreateFromCSC_R      , 8},
  {"LGBM_DatasetCreateFromMat_R"      , (DL_FUNC) &LGBM_DatasetCreateFromMat_R      , 5},
  {"LGBM_DatasetGetSubset_R"          , (DL_FUNC) &LGBM_DatasetGetSubset_R          , 4},
873
  {"LGBM_DatasetSetFeatureNames_R"    , (DL_FUNC) &LGBM_DatasetSetFeatureNames_R    , 2},
874
  {"LGBM_DatasetGetFeatureNames_R"    , (DL_FUNC) &LGBM_DatasetGetFeatureNames_R    , 1},
875
876
877
878
879
880
881
882
  {"LGBM_DatasetSaveBinary_R"         , (DL_FUNC) &LGBM_DatasetSaveBinary_R         , 2},
  {"LGBM_DatasetFree_R"               , (DL_FUNC) &LGBM_DatasetFree_R               , 1},
  {"LGBM_DatasetSetField_R"           , (DL_FUNC) &LGBM_DatasetSetField_R           , 4},
  {"LGBM_DatasetGetFieldSize_R"       , (DL_FUNC) &LGBM_DatasetGetFieldSize_R       , 3},
  {"LGBM_DatasetGetField_R"           , (DL_FUNC) &LGBM_DatasetGetField_R           , 3},
  {"LGBM_DatasetUpdateParamChecking_R", (DL_FUNC) &LGBM_DatasetUpdateParamChecking_R, 2},
  {"LGBM_DatasetGetNumData_R"         , (DL_FUNC) &LGBM_DatasetGetNumData_R         , 2},
  {"LGBM_DatasetGetNumFeature_R"      , (DL_FUNC) &LGBM_DatasetGetNumFeature_R      , 2},
883
  {"LGBM_BoosterCreate_R"             , (DL_FUNC) &LGBM_BoosterCreate_R             , 2},
884
  {"LGBM_BoosterFree_R"               , (DL_FUNC) &LGBM_BoosterFree_R               , 1},
885
886
  {"LGBM_BoosterCreateFromModelfile_R", (DL_FUNC) &LGBM_BoosterCreateFromModelfile_R, 1},
  {"LGBM_BoosterLoadModelFromString_R", (DL_FUNC) &LGBM_BoosterLoadModelFromString_R, 1},
887
888
889
890
891
892
893
894
895
896
897
  {"LGBM_BoosterMerge_R"              , (DL_FUNC) &LGBM_BoosterMerge_R              , 2},
  {"LGBM_BoosterAddValidData_R"       , (DL_FUNC) &LGBM_BoosterAddValidData_R       , 2},
  {"LGBM_BoosterResetTrainingData_R"  , (DL_FUNC) &LGBM_BoosterResetTrainingData_R  , 2},
  {"LGBM_BoosterResetParameter_R"     , (DL_FUNC) &LGBM_BoosterResetParameter_R     , 2},
  {"LGBM_BoosterGetNumClasses_R"      , (DL_FUNC) &LGBM_BoosterGetNumClasses_R      , 2},
  {"LGBM_BoosterUpdateOneIter_R"      , (DL_FUNC) &LGBM_BoosterUpdateOneIter_R      , 1},
  {"LGBM_BoosterUpdateOneIterCustom_R", (DL_FUNC) &LGBM_BoosterUpdateOneIterCustom_R, 4},
  {"LGBM_BoosterRollbackOneIter_R"    , (DL_FUNC) &LGBM_BoosterRollbackOneIter_R    , 1},
  {"LGBM_BoosterGetCurrentIteration_R", (DL_FUNC) &LGBM_BoosterGetCurrentIteration_R, 2},
  {"LGBM_BoosterGetUpperBoundValue_R" , (DL_FUNC) &LGBM_BoosterGetUpperBoundValue_R , 2},
  {"LGBM_BoosterGetLowerBoundValue_R" , (DL_FUNC) &LGBM_BoosterGetLowerBoundValue_R , 2},
898
  {"LGBM_BoosterGetEvalNames_R"       , (DL_FUNC) &LGBM_BoosterGetEvalNames_R       , 1},
899
900
901
902
903
904
905
906
  {"LGBM_BoosterGetEval_R"            , (DL_FUNC) &LGBM_BoosterGetEval_R            , 3},
  {"LGBM_BoosterGetNumPredict_R"      , (DL_FUNC) &LGBM_BoosterGetNumPredict_R      , 3},
  {"LGBM_BoosterGetPredict_R"         , (DL_FUNC) &LGBM_BoosterGetPredict_R         , 3},
  {"LGBM_BoosterPredictForFile_R"     , (DL_FUNC) &LGBM_BoosterPredictForFile_R     , 10},
  {"LGBM_BoosterCalcNumPredict_R"     , (DL_FUNC) &LGBM_BoosterCalcNumPredict_R     , 8},
  {"LGBM_BoosterPredictForCSC_R"      , (DL_FUNC) &LGBM_BoosterPredictForCSC_R      , 14},
  {"LGBM_BoosterPredictForMat_R"      , (DL_FUNC) &LGBM_BoosterPredictForMat_R      , 11},
  {"LGBM_BoosterSaveModel_R"          , (DL_FUNC) &LGBM_BoosterSaveModel_R          , 4},
907
908
  {"LGBM_BoosterSaveModelToString_R"  , (DL_FUNC) &LGBM_BoosterSaveModelToString_R  , 3},
  {"LGBM_BoosterDumpModel_R"          , (DL_FUNC) &LGBM_BoosterDumpModel_R          , 3},
909
910
911
  {NULL, NULL, 0}
};

912
913
LIGHTGBM_C_EXPORT void R_init_lightgbm(DllInfo *dll);

914
915
916
917
void R_init_lightgbm(DllInfo *dll) {
  R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
  R_useDynamicSymbols(dll, FALSE);
}