lightgbm_R.cpp 27.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
28
29
30
#define COL_MAJOR (0)

#define R_API_BEGIN() \
  try {
#define R_API_END() } \
31
32
33
  catch(std::exception& ex) { LGBM_SetLastError(ex.what()); } \
  catch(std::string& ex) { LGBM_SetLastError(ex.c_str()); } \
  catch(...) { LGBM_SetLastError("unknown exception"); }
Guolin Ke's avatar
Guolin Ke committed
34
35
36

#define CHECK_CALL(x) \
  if ((x) != 0) { \
37
    Rf_error(LGBM_GetLastError()); \
Guolin Ke's avatar
Guolin Ke committed
38
39
  }

40
41
using LightGBM::Common::Split;
using LightGBM::Log;
Guolin Ke's avatar
Guolin Ke committed
42

43
44
45
46
SEXP LGBM_HandleIsNull_R(SEXP handle) {
  return Rf_ScalarLogical(R_ExternalPtrAddr(handle) == NULL);
}

47
48
49
50
void _DatasetFinalizer(SEXP handle) {
  LGBM_DatasetFree_R(handle);
}

51
52
SEXP LGBM_DatasetCreateFromFile_R(SEXP filename,
  SEXP parameters,
53
54
  SEXP reference) {
  SEXP ret;
Guolin Ke's avatar
Guolin Ke committed
55
  DatasetHandle handle = nullptr;
56
57
58
59
  DatasetHandle ref = nullptr;
  if (!Rf_isNull(reference)) {
    ref = R_ExternalPtrAddr(reference);
  }
60
61
62
63
64
  const char* filename_ptr = CHAR(PROTECT(Rf_asChar(filename)));
  const char* parameters_ptr = CHAR(PROTECT(Rf_asChar(parameters)));
  R_API_BEGIN();
  CHECK_CALL(LGBM_DatasetCreateFromFile(filename_ptr, parameters_ptr, ref, &handle));
  R_API_END();
65
  ret = PROTECT(R_MakeExternalPtr(handle, R_NilValue, R_NilValue));
66
  R_RegisterCFinalizerEx(ret, _DatasetFinalizer, TRUE);
67
  UNPROTECT(3);
68
  return ret;
Guolin Ke's avatar
Guolin Ke committed
69
70
}

71
72
73
SEXP LGBM_DatasetCreateFromCSC_R(SEXP indptr,
  SEXP indices,
  SEXP data,
74
75
76
  SEXP num_indptr,
  SEXP nelem,
  SEXP num_row,
77
  SEXP parameters,
78
79
  SEXP reference) {
  SEXP ret;
80
81
82
  const int* p_indptr = INTEGER(indptr);
  const int* p_indices = INTEGER(indices);
  const double* p_data = REAL(data);
83
84
85
  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));
86
  const char* parameters_ptr = CHAR(PROTECT(Rf_asChar(parameters)));
Guolin Ke's avatar
Guolin Ke committed
87
  DatasetHandle handle = nullptr;
88
89
90
91
  DatasetHandle ref = nullptr;
  if (!Rf_isNull(reference)) {
    ref = R_ExternalPtrAddr(reference);
  }
92
  R_API_BEGIN();
Guolin Ke's avatar
Guolin Ke committed
93
94
  CHECK_CALL(LGBM_DatasetCreateFromCSC(p_indptr, C_API_DTYPE_INT32, p_indices,
    p_data, C_API_DTYPE_FLOAT64, nindptr, ndata,
95
96
    nrow, parameters_ptr, ref, &handle));
  R_API_END();
97
  ret = PROTECT(R_MakeExternalPtr(handle, R_NilValue, R_NilValue));
98
  R_RegisterCFinalizerEx(ret, _DatasetFinalizer, TRUE);
99
  UNPROTECT(2);
100
  return ret;
Guolin Ke's avatar
Guolin Ke committed
101
102
}

103
SEXP LGBM_DatasetCreateFromMat_R(SEXP data,
104
105
  SEXP num_row,
  SEXP num_col,
106
  SEXP parameters,
107
108
  SEXP reference) {
  SEXP ret;
109
110
  int32_t nrow = static_cast<int32_t>(Rf_asInteger(num_row));
  int32_t ncol = static_cast<int32_t>(Rf_asInteger(num_col));
111
  double* p_mat = REAL(data);
112
  const char* parameters_ptr = CHAR(PROTECT(Rf_asChar(parameters)));
Guolin Ke's avatar
Guolin Ke committed
113
  DatasetHandle handle = nullptr;
114
115
116
117
  DatasetHandle ref = nullptr;
  if (!Rf_isNull(reference)) {
    ref = R_ExternalPtrAddr(reference);
  }
118
  R_API_BEGIN();
Guolin Ke's avatar
Guolin Ke committed
119
  CHECK_CALL(LGBM_DatasetCreateFromMat(p_mat, C_API_DTYPE_FLOAT64, nrow, ncol, COL_MAJOR,
120
121
    parameters_ptr, ref, &handle));
  R_API_END();
122
  ret = PROTECT(R_MakeExternalPtr(handle, R_NilValue, R_NilValue));
123
  R_RegisterCFinalizerEx(ret, _DatasetFinalizer, TRUE);
124
  UNPROTECT(2);
125
  return ret;
Guolin Ke's avatar
Guolin Ke committed
126
127
}

128
SEXP LGBM_DatasetGetSubset_R(SEXP handle,
129
  SEXP used_row_indices,
130
  SEXP len_used_row_indices,
131
132
  SEXP parameters) {
  SEXP ret;
133
134
  int32_t len = static_cast<int32_t>(Rf_asInteger(len_used_row_indices));
  std::vector<int32_t> idxvec(len);
135
  // convert from one-based to zero-based index
Guolin Ke's avatar
Guolin Ke committed
136
#pragma omp parallel for schedule(static, 512) if (len >= 1024)
137
138
  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
139
  }
140
  const char* parameters_ptr = CHAR(PROTECT(Rf_asChar(parameters)));
Guolin Ke's avatar
Guolin Ke committed
141
  DatasetHandle res = nullptr;
142
  R_API_BEGIN();
143
  CHECK_CALL(LGBM_DatasetGetSubset(R_ExternalPtrAddr(handle),
144
    idxvec.data(), len, parameters_ptr,
Guolin Ke's avatar
Guolin Ke committed
145
    &res));
146
  R_API_END();
147
  ret = PROTECT(R_MakeExternalPtr(res, R_NilValue, R_NilValue));
148
  R_RegisterCFinalizerEx(ret, _DatasetFinalizer, TRUE);
149
  UNPROTECT(2);
150
  return ret;
Guolin Ke's avatar
Guolin Ke committed
151
152
}

153
SEXP LGBM_DatasetSetFeatureNames_R(SEXP handle,
154
  SEXP feature_names) {
155
  auto vec_names = Split(CHAR(PROTECT(Rf_asChar(feature_names))), '\t');
Guolin Ke's avatar
Guolin Ke committed
156
157
158
159
160
  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());
  }
161
  R_API_BEGIN();
162
  CHECK_CALL(LGBM_DatasetSetFeatureNames(R_ExternalPtrAddr(handle),
Guolin Ke's avatar
Guolin Ke committed
163
164
    vec_sptr.data(), len));
  R_API_END();
165
166
  UNPROTECT(1);
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
167
168
}

169
SEXP LGBM_DatasetGetFeatureNames_R(SEXP handle) {
170
  SEXP feature_names;
Guolin Ke's avatar
Guolin Ke committed
171
  int len = 0;
172
  R_API_BEGIN();
173
  CHECK_CALL(LGBM_DatasetGetNumFeature(R_ExternalPtrAddr(handle), &len));
174
  R_API_END();
175
  const size_t reserved_string_size = 256;
Guolin Ke's avatar
Guolin Ke committed
176
177
178
  std::vector<std::vector<char>> names(len);
  std::vector<char*> ptr_names(len);
  for (int i = 0; i < len; ++i) {
179
    names[i].resize(reserved_string_size);
Guolin Ke's avatar
Guolin Ke committed
180
181
182
    ptr_names[i] = names[i].data();
  }
  int out_len;
183
  size_t required_string_size;
184
  R_API_BEGIN();
185
186
  CHECK_CALL(
    LGBM_DatasetGetFeatureNames(
187
      R_ExternalPtrAddr(handle),
188
189
190
      len, &out_len,
      reserved_string_size, &required_string_size,
      ptr_names.data()));
191
  R_API_END();
192
193
194
195
196
197
198
  // 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();
    }
199
    R_API_BEGIN();
200
201
    CHECK_CALL(
      LGBM_DatasetGetFeatureNames(
202
        R_ExternalPtrAddr(handle),
203
204
205
206
207
        len,
        &out_len,
        required_string_size,
        &required_string_size,
        ptr_names.data()));
208
    R_API_END();
209
  }
Nikita Titov's avatar
Nikita Titov committed
210
  CHECK_EQ(len, out_len);
211
212
213
214
215
216
  feature_names = PROTECT(Rf_allocVector(STRSXP, len));
  for (int i = 0; i < len; ++i) {
    SET_STRING_ELT(feature_names, i, Rf_mkChar(ptr_names[i]));
  }
  UNPROTECT(1);
  return feature_names;
Guolin Ke's avatar
Guolin Ke committed
217
218
}

219
SEXP LGBM_DatasetSaveBinary_R(SEXP handle,
220
  SEXP filename) {
221
  const char* filename_ptr = CHAR(PROTECT(Rf_asChar(filename)));
Guolin Ke's avatar
Guolin Ke committed
222
  R_API_BEGIN();
223
  CHECK_CALL(LGBM_DatasetSaveBinary(R_ExternalPtrAddr(handle),
224
    filename_ptr));
Guolin Ke's avatar
Guolin Ke committed
225
  R_API_END();
226
227
  UNPROTECT(1);
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
228
229
}

230
SEXP LGBM_DatasetFree_R(SEXP handle) {
Guolin Ke's avatar
Guolin Ke committed
231
  R_API_BEGIN();
232
  if (!Rf_isNull(handle) && R_ExternalPtrAddr(handle)) {
233
234
    CHECK_CALL(LGBM_DatasetFree(R_ExternalPtrAddr(handle)));
    R_ClearExternalPtr(handle);
Guolin Ke's avatar
Guolin Ke committed
235
236
  }
  R_API_END();
237
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
238
239
}

240
SEXP LGBM_DatasetSetField_R(SEXP handle,
241
  SEXP field_name,
242
  SEXP field_data,
243
  SEXP num_element) {
244
  int len = Rf_asInteger(num_element);
245
246
  const char* name = CHAR(PROTECT(Rf_asChar(field_name)));
  R_API_BEGIN();
Guolin Ke's avatar
Guolin Ke committed
247
248
  if (!strcmp("group", name) || !strcmp("query", name)) {
    std::vector<int32_t> vec(len);
Guolin Ke's avatar
Guolin Ke committed
249
#pragma omp parallel for schedule(static, 512) if (len >= 1024)
Guolin Ke's avatar
Guolin Ke committed
250
    for (int i = 0; i < len; ++i) {
251
      vec[i] = static_cast<int32_t>(INTEGER(field_data)[i]);
Guolin Ke's avatar
Guolin Ke committed
252
    }
253
    CHECK_CALL(LGBM_DatasetSetField(R_ExternalPtrAddr(handle), name, vec.data(), len, C_API_DTYPE_INT32));
254
  } else if (!strcmp("init_score", name)) {
255
    CHECK_CALL(LGBM_DatasetSetField(R_ExternalPtrAddr(handle), name, REAL(field_data), len, C_API_DTYPE_FLOAT64));
Guolin Ke's avatar
Guolin Ke committed
256
257
  } else {
    std::vector<float> vec(len);
Guolin Ke's avatar
Guolin Ke committed
258
#pragma omp parallel for schedule(static, 512) if (len >= 1024)
Guolin Ke's avatar
Guolin Ke committed
259
    for (int i = 0; i < len; ++i) {
260
      vec[i] = static_cast<float>(REAL(field_data)[i]);
Guolin Ke's avatar
Guolin Ke committed
261
    }
262
    CHECK_CALL(LGBM_DatasetSetField(R_ExternalPtrAddr(handle), name, vec.data(), len, C_API_DTYPE_FLOAT32));
Guolin Ke's avatar
Guolin Ke committed
263
264
  }
  R_API_END();
265
266
  UNPROTECT(1);
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
267
268
}

269
SEXP LGBM_DatasetGetField_R(SEXP handle,
270
  SEXP field_name,
271
  SEXP field_data) {
272
  const char* name = CHAR(PROTECT(Rf_asChar(field_name)));
Guolin Ke's avatar
Guolin Ke committed
273
274
275
  int out_len = 0;
  int out_type = 0;
  const void* res;
276
  R_API_BEGIN();
277
  CHECK_CALL(LGBM_DatasetGetField(R_ExternalPtrAddr(handle), name, &out_len, &res, &out_type));
Guolin Ke's avatar
Guolin Ke committed
278
279
280
  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
281
#pragma omp parallel for schedule(static, 512) if (out_len >= 1024)
Guolin Ke's avatar
Guolin Ke committed
282
    for (int i = 0; i < out_len - 1; ++i) {
283
      INTEGER(field_data)[i] = p_data[i + 1] - p_data[i];
Guolin Ke's avatar
Guolin Ke committed
284
    }
Guolin Ke's avatar
Guolin Ke committed
285
286
  } else if (!strcmp("init_score", name)) {
    auto p_data = reinterpret_cast<const double*>(res);
Guolin Ke's avatar
Guolin Ke committed
287
#pragma omp parallel for schedule(static, 512) if (out_len >= 1024)
Guolin Ke's avatar
Guolin Ke committed
288
    for (int i = 0; i < out_len; ++i) {
289
      REAL(field_data)[i] = p_data[i];
Guolin Ke's avatar
Guolin Ke committed
290
    }
Guolin Ke's avatar
Guolin Ke committed
291
292
  } else {
    auto p_data = reinterpret_cast<const float*>(res);
Guolin Ke's avatar
Guolin Ke committed
293
#pragma omp parallel for schedule(static, 512) if (out_len >= 1024)
Guolin Ke's avatar
Guolin Ke committed
294
    for (int i = 0; i < out_len; ++i) {
295
      REAL(field_data)[i] = p_data[i];
Guolin Ke's avatar
Guolin Ke committed
296
297
298
    }
  }
  R_API_END();
299
300
  UNPROTECT(1);
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
301
302
}

303
SEXP LGBM_DatasetGetFieldSize_R(SEXP handle,
304
  SEXP field_name,
305
  SEXP out) {
306
  const char* name = CHAR(PROTECT(Rf_asChar(field_name)));
Guolin Ke's avatar
Guolin Ke committed
307
308
309
  int out_len = 0;
  int out_type = 0;
  const void* res;
310
  R_API_BEGIN();
311
  CHECK_CALL(LGBM_DatasetGetField(R_ExternalPtrAddr(handle), name, &out_len, &res, &out_type));
Guolin Ke's avatar
Guolin Ke committed
312
313
314
  if (!strcmp("group", name) || !strcmp("query", name)) {
    out_len -= 1;
  }
315
  INTEGER(out)[0] = out_len;
Guolin Ke's avatar
Guolin Ke committed
316
  R_API_END();
317
318
  UNPROTECT(1);
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
319
320
}

321
322
SEXP LGBM_DatasetUpdateParamChecking_R(SEXP old_params,
  SEXP new_params) {
323
324
  const char* old_params_ptr = CHAR(PROTECT(Rf_asChar(old_params)));
  const char* new_params_ptr = CHAR(PROTECT(Rf_asChar(new_params)));
325
  R_API_BEGIN();
326
  CHECK_CALL(LGBM_DatasetUpdateParamChecking(old_params_ptr, new_params_ptr));
327
  R_API_END();
328
329
  UNPROTECT(2);
  return R_NilValue;
330
331
}

332
SEXP LGBM_DatasetGetNumData_R(SEXP handle, SEXP out) {
Guolin Ke's avatar
Guolin Ke committed
333
334
  int nrow;
  R_API_BEGIN();
335
  CHECK_CALL(LGBM_DatasetGetNumData(R_ExternalPtrAddr(handle), &nrow));
336
  INTEGER(out)[0] = nrow;
Guolin Ke's avatar
Guolin Ke committed
337
  R_API_END();
338
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
339
340
}

341
SEXP LGBM_DatasetGetNumFeature_R(SEXP handle,
342
  SEXP out) {
Guolin Ke's avatar
Guolin Ke committed
343
344
  int nfeature;
  R_API_BEGIN();
345
  CHECK_CALL(LGBM_DatasetGetNumFeature(R_ExternalPtrAddr(handle), &nfeature));
346
  INTEGER(out)[0] = nfeature;
Guolin Ke's avatar
Guolin Ke committed
347
  R_API_END();
348
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
349
350
351
352
}

// --- start Booster interfaces

353
354
355
356
void _BoosterFinalizer(SEXP handle) {
  LGBM_BoosterFree_R(handle);
}

357
SEXP LGBM_BoosterFree_R(SEXP handle) {
Guolin Ke's avatar
Guolin Ke committed
358
  R_API_BEGIN();
359
  if (!Rf_isNull(handle) && R_ExternalPtrAddr(handle)) {
360
361
    CHECK_CALL(LGBM_BoosterFree(R_ExternalPtrAddr(handle)));
    R_ClearExternalPtr(handle);
Guolin Ke's avatar
Guolin Ke committed
362
363
  }
  R_API_END();
364
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
365
366
}

367
368
369
SEXP LGBM_BoosterCreate_R(SEXP train_data,
  SEXP parameters) {
  SEXP ret;
370
  const char* parameters_ptr = CHAR(PROTECT(Rf_asChar(parameters)));
Guolin Ke's avatar
Guolin Ke committed
371
  BoosterHandle handle = nullptr;
372
373
374
  R_API_BEGIN();
  CHECK_CALL(LGBM_BoosterCreate(R_ExternalPtrAddr(train_data), parameters_ptr, &handle));
  R_API_END();
375
  ret = PROTECT(R_MakeExternalPtr(handle, R_NilValue, R_NilValue));
376
  R_RegisterCFinalizerEx(ret, _BoosterFinalizer, TRUE);
377
  UNPROTECT(2);
378
  return ret;
Guolin Ke's avatar
Guolin Ke committed
379
380
}

381
382
SEXP LGBM_BoosterCreateFromModelfile_R(SEXP filename) {
  SEXP ret;
Guolin Ke's avatar
Guolin Ke committed
383
  int out_num_iterations = 0;
384
  const char* filename_ptr = CHAR(PROTECT(Rf_asChar(filename)));
Guolin Ke's avatar
Guolin Ke committed
385
  BoosterHandle handle = nullptr;
386
387
388
  R_API_BEGIN();
  CHECK_CALL(LGBM_BoosterCreateFromModelfile(filename_ptr, &out_num_iterations, &handle));
  R_API_END();
389
  ret = PROTECT(R_MakeExternalPtr(handle, R_NilValue, R_NilValue));
390
  R_RegisterCFinalizerEx(ret, _BoosterFinalizer, TRUE);
391
  UNPROTECT(2);
392
  return ret;
Guolin Ke's avatar
Guolin Ke committed
393
394
}

395
396
SEXP LGBM_BoosterLoadModelFromString_R(SEXP model_str) {
  SEXP ret;
397
  int out_num_iterations = 0;
398
  const char* model_str_ptr = CHAR(PROTECT(Rf_asChar(model_str)));
Guolin Ke's avatar
Guolin Ke committed
399
  BoosterHandle handle = nullptr;
400
401
402
  R_API_BEGIN();
  CHECK_CALL(LGBM_BoosterLoadModelFromString(model_str_ptr, &out_num_iterations, &handle));
  R_API_END();
403
  ret = PROTECT(R_MakeExternalPtr(handle, R_NilValue, R_NilValue));
404
  R_RegisterCFinalizerEx(ret, _BoosterFinalizer, TRUE);
405
  UNPROTECT(2);
406
  return ret;
407
408
}

409
410
SEXP LGBM_BoosterMerge_R(SEXP handle,
  SEXP other_handle) {
Guolin Ke's avatar
Guolin Ke committed
411
  R_API_BEGIN();
412
  CHECK_CALL(LGBM_BoosterMerge(R_ExternalPtrAddr(handle), R_ExternalPtrAddr(other_handle)));
Guolin Ke's avatar
Guolin Ke committed
413
  R_API_END();
414
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
415
416
}

417
418
SEXP LGBM_BoosterAddValidData_R(SEXP handle,
  SEXP valid_data) {
Guolin Ke's avatar
Guolin Ke committed
419
  R_API_BEGIN();
420
  CHECK_CALL(LGBM_BoosterAddValidData(R_ExternalPtrAddr(handle), R_ExternalPtrAddr(valid_data)));
Guolin Ke's avatar
Guolin Ke committed
421
  R_API_END();
422
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
423
424
}

425
426
SEXP LGBM_BoosterResetTrainingData_R(SEXP handle,
  SEXP train_data) {
Guolin Ke's avatar
Guolin Ke committed
427
  R_API_BEGIN();
428
  CHECK_CALL(LGBM_BoosterResetTrainingData(R_ExternalPtrAddr(handle), R_ExternalPtrAddr(train_data)));
Guolin Ke's avatar
Guolin Ke committed
429
  R_API_END();
430
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
431
432
}

433
SEXP LGBM_BoosterResetParameter_R(SEXP handle,
434
  SEXP parameters) {
435
  const char* parameters_ptr = CHAR(PROTECT(Rf_asChar(parameters)));
Guolin Ke's avatar
Guolin Ke committed
436
  R_API_BEGIN();
437
  CHECK_CALL(LGBM_BoosterResetParameter(R_ExternalPtrAddr(handle), parameters_ptr));
Guolin Ke's avatar
Guolin Ke committed
438
  R_API_END();
439
440
  UNPROTECT(1);
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
441
442
}

443
SEXP LGBM_BoosterGetNumClasses_R(SEXP handle,
444
  SEXP out) {
Guolin Ke's avatar
Guolin Ke committed
445
446
  int num_class;
  R_API_BEGIN();
447
  CHECK_CALL(LGBM_BoosterGetNumClasses(R_ExternalPtrAddr(handle), &num_class));
448
  INTEGER(out)[0] = num_class;
Guolin Ke's avatar
Guolin Ke committed
449
  R_API_END();
450
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
451
452
}

453
SEXP LGBM_BoosterUpdateOneIter_R(SEXP handle) {
Guolin Ke's avatar
Guolin Ke committed
454
455
  int is_finished = 0;
  R_API_BEGIN();
456
  CHECK_CALL(LGBM_BoosterUpdateOneIter(R_ExternalPtrAddr(handle), &is_finished));
Guolin Ke's avatar
Guolin Ke committed
457
  R_API_END();
458
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
459
460
}

461
SEXP LGBM_BoosterUpdateOneIterCustom_R(SEXP handle,
462
463
  SEXP grad,
  SEXP hess,
464
  SEXP len) {
Guolin Ke's avatar
Guolin Ke committed
465
466
  int is_finished = 0;
  R_API_BEGIN();
467
  int int_len = Rf_asInteger(len);
Guolin Ke's avatar
Guolin Ke committed
468
  std::vector<float> tgrad(int_len), thess(int_len);
Guolin Ke's avatar
Guolin Ke committed
469
#pragma omp parallel for schedule(static, 512) if (int_len >= 1024)
Guolin Ke's avatar
Guolin Ke committed
470
  for (int j = 0; j < int_len; ++j) {
471
472
    tgrad[j] = static_cast<float>(REAL(grad)[j]);
    thess[j] = static_cast<float>(REAL(hess)[j]);
Guolin Ke's avatar
Guolin Ke committed
473
  }
474
  CHECK_CALL(LGBM_BoosterUpdateOneIterCustom(R_ExternalPtrAddr(handle), tgrad.data(), thess.data(), &is_finished));
Guolin Ke's avatar
Guolin Ke committed
475
  R_API_END();
476
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
477
478
}

479
SEXP LGBM_BoosterRollbackOneIter_R(SEXP handle) {
Guolin Ke's avatar
Guolin Ke committed
480
  R_API_BEGIN();
481
  CHECK_CALL(LGBM_BoosterRollbackOneIter(R_ExternalPtrAddr(handle)));
Guolin Ke's avatar
Guolin Ke committed
482
  R_API_END();
483
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
484
485
}

486
SEXP LGBM_BoosterGetCurrentIteration_R(SEXP handle,
487
  SEXP out) {
Guolin Ke's avatar
Guolin Ke committed
488
489
  int out_iteration;
  R_API_BEGIN();
490
  CHECK_CALL(LGBM_BoosterGetCurrentIteration(R_ExternalPtrAddr(handle), &out_iteration));
491
  INTEGER(out)[0] = out_iteration;
Guolin Ke's avatar
Guolin Ke committed
492
  R_API_END();
493
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
494
495
}

496
SEXP LGBM_BoosterGetUpperBoundValue_R(SEXP handle,
497
  SEXP out_result) {
498
  R_API_BEGIN();
499
  double* ptr_ret = REAL(out_result);
500
  CHECK_CALL(LGBM_BoosterGetUpperBoundValue(R_ExternalPtrAddr(handle), ptr_ret));
501
  R_API_END();
502
  return R_NilValue;
503
504
}

505
SEXP LGBM_BoosterGetLowerBoundValue_R(SEXP handle,
506
  SEXP out_result) {
507
  R_API_BEGIN();
508
  double* ptr_ret = REAL(out_result);
509
  CHECK_CALL(LGBM_BoosterGetLowerBoundValue(R_ExternalPtrAddr(handle), ptr_ret));
510
  R_API_END();
511
  return R_NilValue;
512
513
}

514
SEXP LGBM_BoosterGetEvalNames_R(SEXP handle) {
515
  SEXP eval_names;
Guolin Ke's avatar
Guolin Ke committed
516
  int len;
517
  R_API_BEGIN();
518
  CHECK_CALL(LGBM_BoosterGetEvalCounts(R_ExternalPtrAddr(handle), &len));
519
  R_API_END();
520
  const size_t reserved_string_size = 128;
Guolin Ke's avatar
Guolin Ke committed
521
522
523
  std::vector<std::vector<char>> names(len);
  std::vector<char*> ptr_names(len);
  for (int i = 0; i < len; ++i) {
524
    names[i].resize(reserved_string_size);
Guolin Ke's avatar
Guolin Ke committed
525
526
    ptr_names[i] = names[i].data();
  }
527

Guolin Ke's avatar
Guolin Ke committed
528
  int out_len;
529
  size_t required_string_size;
530
  R_API_BEGIN();
531
532
  CHECK_CALL(
    LGBM_BoosterGetEvalNames(
533
      R_ExternalPtrAddr(handle),
534
535
536
      len, &out_len,
      reserved_string_size, &required_string_size,
      ptr_names.data()));
537
  R_API_END();
538
539
540
541
542
543
544
  // 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();
    }
545
    R_API_BEGIN();
546
547
    CHECK_CALL(
      LGBM_BoosterGetEvalNames(
548
        R_ExternalPtrAddr(handle),
549
550
551
552
553
        len,
        &out_len,
        required_string_size,
        &required_string_size,
        ptr_names.data()));
554
    R_API_END();
555
  }
Nikita Titov's avatar
Nikita Titov committed
556
  CHECK_EQ(out_len, len);
557
558
559
560
561
562
  eval_names = PROTECT(Rf_allocVector(STRSXP, len));
  for (int i = 0; i < len; ++i) {
    SET_STRING_ELT(eval_names, i, Rf_mkChar(ptr_names[i]));
  }
  UNPROTECT(1);
  return eval_names;
Guolin Ke's avatar
Guolin Ke committed
563
564
}

565
SEXP LGBM_BoosterGetEval_R(SEXP handle,
566
  SEXP data_idx,
567
  SEXP out_result) {
Guolin Ke's avatar
Guolin Ke committed
568
569
  R_API_BEGIN();
  int len;
570
  CHECK_CALL(LGBM_BoosterGetEvalCounts(R_ExternalPtrAddr(handle), &len));
571
  double* ptr_ret = REAL(out_result);
Guolin Ke's avatar
Guolin Ke committed
572
  int out_len;
573
  CHECK_CALL(LGBM_BoosterGetEval(R_ExternalPtrAddr(handle), Rf_asInteger(data_idx), &out_len, ptr_ret));
Nikita Titov's avatar
Nikita Titov committed
574
  CHECK_EQ(out_len, len);
Guolin Ke's avatar
Guolin Ke committed
575
  R_API_END();
576
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
577
578
}

579
SEXP LGBM_BoosterGetNumPredict_R(SEXP handle,
580
  SEXP data_idx,
581
  SEXP out) {
Guolin Ke's avatar
Guolin Ke committed
582
583
  R_API_BEGIN();
  int64_t len;
584
  CHECK_CALL(LGBM_BoosterGetNumPredict(R_ExternalPtrAddr(handle), Rf_asInteger(data_idx), &len));
585
  INTEGER(out)[0] = static_cast<int>(len);
Guolin Ke's avatar
Guolin Ke committed
586
  R_API_END();
587
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
588
589
}

590
SEXP LGBM_BoosterGetPredict_R(SEXP handle,
591
  SEXP data_idx,
592
  SEXP out_result) {
Guolin Ke's avatar
Guolin Ke committed
593
  R_API_BEGIN();
594
  double* ptr_ret = REAL(out_result);
Guolin Ke's avatar
Guolin Ke committed
595
  int64_t out_len;
596
  CHECK_CALL(LGBM_BoosterGetPredict(R_ExternalPtrAddr(handle), Rf_asInteger(data_idx), &out_len, ptr_ret));
Guolin Ke's avatar
Guolin Ke committed
597
  R_API_END();
598
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
599
600
}

601
int GetPredictType(SEXP is_rawscore, SEXP is_leafidx, SEXP is_predcontrib) {
Guolin Ke's avatar
Guolin Ke committed
602
  int pred_type = C_API_PREDICT_NORMAL;
603
  if (Rf_asInteger(is_rawscore)) {
Guolin Ke's avatar
Guolin Ke committed
604
605
    pred_type = C_API_PREDICT_RAW_SCORE;
  }
606
  if (Rf_asInteger(is_leafidx)) {
Guolin Ke's avatar
Guolin Ke committed
607
608
    pred_type = C_API_PREDICT_LEAF_INDEX;
  }
609
  if (Rf_asInteger(is_predcontrib)) {
610
611
    pred_type = C_API_PREDICT_CONTRIB;
  }
Guolin Ke's avatar
Guolin Ke committed
612
613
614
  return pred_type;
}

615
SEXP LGBM_BoosterPredictForFile_R(SEXP handle,
616
  SEXP data_filename,
617
618
619
620
621
622
  SEXP data_has_header,
  SEXP is_rawscore,
  SEXP is_leafidx,
  SEXP is_predcontrib,
  SEXP start_iteration,
  SEXP num_iteration,
623
624
  SEXP parameter,
  SEXP result_filename) {
625
626
627
  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)));
628
  int pred_type = GetPredictType(is_rawscore, is_leafidx, is_predcontrib);
629
630
631
632
  R_API_BEGIN();
  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));
Guolin Ke's avatar
Guolin Ke committed
633
  R_API_END();
634
635
  UNPROTECT(3);
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
636
637
}

638
SEXP LGBM_BoosterCalcNumPredict_R(SEXP handle,
639
640
641
642
643
644
  SEXP num_row,
  SEXP is_rawscore,
  SEXP is_leafidx,
  SEXP is_predcontrib,
  SEXP start_iteration,
  SEXP num_iteration,
645
  SEXP out_len) {
Guolin Ke's avatar
Guolin Ke committed
646
  R_API_BEGIN();
647
  int pred_type = GetPredictType(is_rawscore, is_leafidx, is_predcontrib);
Guolin Ke's avatar
Guolin Ke committed
648
  int64_t len = 0;
649
  CHECK_CALL(LGBM_BoosterCalcNumPredict(R_ExternalPtrAddr(handle), Rf_asInteger(num_row),
650
    pred_type, Rf_asInteger(start_iteration), Rf_asInteger(num_iteration), &len));
651
  INTEGER(out_len)[0] = static_cast<int>(len);
Guolin Ke's avatar
Guolin Ke committed
652
  R_API_END();
653
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
654
655
}

656
SEXP LGBM_BoosterPredictForCSC_R(SEXP handle,
657
658
659
  SEXP indptr,
  SEXP indices,
  SEXP data,
660
661
662
663
664
665
666
667
  SEXP num_indptr,
  SEXP nelem,
  SEXP num_row,
  SEXP is_rawscore,
  SEXP is_leafidx,
  SEXP is_predcontrib,
  SEXP start_iteration,
  SEXP num_iteration,
668
  SEXP parameter,
669
  SEXP out_result) {
670
  int pred_type = GetPredictType(is_rawscore, is_leafidx, is_predcontrib);
671
  const int* p_indptr = INTEGER(indptr);
672
  const int32_t* p_indices = reinterpret_cast<const int32_t*>(INTEGER(indices));
673
  const double* p_data = REAL(data);
674
675
676
  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));
677
  double* ptr_ret = REAL(out_result);
Guolin Ke's avatar
Guolin Ke committed
678
  int64_t out_len;
679
680
  const char* parameter_ptr = CHAR(PROTECT(Rf_asChar(parameter)));
  R_API_BEGIN();
681
  CHECK_CALL(LGBM_BoosterPredictForCSC(R_ExternalPtrAddr(handle),
Guolin Ke's avatar
Guolin Ke committed
682
683
    p_indptr, C_API_DTYPE_INT32, p_indices,
    p_data, C_API_DTYPE_FLOAT64, nindptr, ndata,
684
    nrow, pred_type, Rf_asInteger(start_iteration), Rf_asInteger(num_iteration), parameter_ptr, &out_len, ptr_ret));
Guolin Ke's avatar
Guolin Ke committed
685
  R_API_END();
686
687
  UNPROTECT(1);
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
688
689
}

690
SEXP LGBM_BoosterPredictForMat_R(SEXP handle,
691
  SEXP data,
692
693
694
695
696
697
698
  SEXP num_row,
  SEXP num_col,
  SEXP is_rawscore,
  SEXP is_leafidx,
  SEXP is_predcontrib,
  SEXP start_iteration,
  SEXP num_iteration,
699
  SEXP parameter,
700
  SEXP out_result) {
701
  int pred_type = GetPredictType(is_rawscore, is_leafidx, is_predcontrib);
702
703
  int32_t nrow = static_cast<int32_t>(Rf_asInteger(num_row));
  int32_t ncol = static_cast<int32_t>(Rf_asInteger(num_col));
704
705
  const double* p_mat = REAL(data);
  double* ptr_ret = REAL(out_result);
706
  const char* parameter_ptr = CHAR(PROTECT(Rf_asChar(parameter)));
Guolin Ke's avatar
Guolin Ke committed
707
  int64_t out_len;
708
  R_API_BEGIN();
709
  CHECK_CALL(LGBM_BoosterPredictForMat(R_ExternalPtrAddr(handle),
Guolin Ke's avatar
Guolin Ke committed
710
    p_mat, C_API_DTYPE_FLOAT64, nrow, ncol, COL_MAJOR,
711
    pred_type, Rf_asInteger(start_iteration), Rf_asInteger(num_iteration), parameter_ptr, &out_len, ptr_ret));
Guolin Ke's avatar
Guolin Ke committed
712
  R_API_END();
713
714
  UNPROTECT(1);
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
715
716
}

717
SEXP LGBM_BoosterSaveModel_R(SEXP handle,
718
719
  SEXP num_iteration,
  SEXP feature_importance_type,
720
  SEXP filename) {
721
  const char* filename_ptr = CHAR(PROTECT(Rf_asChar(filename)));
Guolin Ke's avatar
Guolin Ke committed
722
  R_API_BEGIN();
723
  CHECK_CALL(LGBM_BoosterSaveModel(R_ExternalPtrAddr(handle), 0, Rf_asInteger(num_iteration), Rf_asInteger(feature_importance_type), filename_ptr));
Guolin Ke's avatar
Guolin Ke committed
724
  R_API_END();
725
726
  UNPROTECT(1);
  return R_NilValue;
Guolin Ke's avatar
Guolin Ke committed
727
728
}

729
SEXP LGBM_BoosterSaveModelToString_R(SEXP handle,
730
  SEXP num_iteration,
731
732
  SEXP feature_importance_type) {
  SEXP model_str;
733
  int64_t out_len = 0;
734
  int64_t buf_len = 1024 * 1024;
735
736
  int num_iter = Rf_asInteger(num_iteration);
  int importance_type = Rf_asInteger(feature_importance_type);
737
  std::vector<char> inner_char_buf(buf_len);
738
  R_API_BEGIN();
739
  CHECK_CALL(LGBM_BoosterSaveModelToString(R_ExternalPtrAddr(handle), 0, num_iter, importance_type, buf_len, &out_len, inner_char_buf.data()));
740
  R_API_END();
741
742
743
  // 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);
744
    R_API_BEGIN();
745
    CHECK_CALL(LGBM_BoosterSaveModelToString(R_ExternalPtrAddr(handle), 0, num_iter, importance_type, out_len, &out_len, inner_char_buf.data()));
746
    R_API_END();
747
748
749
750
751
  }
  model_str = PROTECT(Rf_allocVector(STRSXP, 1));
  SET_STRING_ELT(model_str, 0, Rf_mkChar(inner_char_buf.data()));
  UNPROTECT(1);
  return model_str;
752
753
}

754
SEXP LGBM_BoosterDumpModel_R(SEXP handle,
755
  SEXP num_iteration,
756
757
  SEXP feature_importance_type) {
  SEXP model_str;
758
  int64_t out_len = 0;
759
  int64_t buf_len = 1024 * 1024;
760
761
  int num_iter = Rf_asInteger(num_iteration);
  int importance_type = Rf_asInteger(feature_importance_type);
762
  std::vector<char> inner_char_buf(buf_len);
763
  R_API_BEGIN();
764
  CHECK_CALL(LGBM_BoosterDumpModel(R_ExternalPtrAddr(handle), 0, num_iter, importance_type, buf_len, &out_len, inner_char_buf.data()));
765
  R_API_END();
766
767
768
  // 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);
769
    R_API_BEGIN();
770
    CHECK_CALL(LGBM_BoosterDumpModel(R_ExternalPtrAddr(handle), 0, num_iter, importance_type, out_len, &out_len, inner_char_buf.data()));
771
    R_API_END();
772
773
774
775
776
  }
  model_str = PROTECT(Rf_allocVector(STRSXP, 1));
  SET_STRING_ELT(model_str, 0, Rf_mkChar(inner_char_buf.data()));
  UNPROTECT(1);
  return model_str;
Guolin Ke's avatar
Guolin Ke committed
777
}
778
779
780

// .Call() calls
static const R_CallMethodDef CallEntries[] = {
781
782
783
784
785
  {"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},
786
  {"LGBM_DatasetSetFeatureNames_R"    , (DL_FUNC) &LGBM_DatasetSetFeatureNames_R    , 2},
787
  {"LGBM_DatasetGetFeatureNames_R"    , (DL_FUNC) &LGBM_DatasetGetFeatureNames_R    , 1},
788
789
790
791
792
793
794
795
  {"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},
796
  {"LGBM_BoosterCreate_R"             , (DL_FUNC) &LGBM_BoosterCreate_R             , 2},
797
  {"LGBM_BoosterFree_R"               , (DL_FUNC) &LGBM_BoosterFree_R               , 1},
798
799
  {"LGBM_BoosterCreateFromModelfile_R", (DL_FUNC) &LGBM_BoosterCreateFromModelfile_R, 1},
  {"LGBM_BoosterLoadModelFromString_R", (DL_FUNC) &LGBM_BoosterLoadModelFromString_R, 1},
800
801
802
803
804
805
806
807
808
809
810
  {"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},
811
  {"LGBM_BoosterGetEvalNames_R"       , (DL_FUNC) &LGBM_BoosterGetEvalNames_R       , 1},
812
813
814
815
816
817
818
819
  {"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},
820
821
  {"LGBM_BoosterSaveModelToString_R"  , (DL_FUNC) &LGBM_BoosterSaveModelToString_R  , 3},
  {"LGBM_BoosterDumpModel_R"          , (DL_FUNC) &LGBM_BoosterDumpModel_R          , 3},
822
823
824
  {NULL, NULL, 0}
};

825
826
LIGHTGBM_C_EXPORT void R_init_lightgbm(DllInfo *dll);

827
828
829
830
void R_init_lightgbm(DllInfo *dll) {
  R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
  R_useDynamicSymbols(dll, FALSE);
}