Changes in version 1.1.1 (2026-05-28) - CRAN resubmission. Addresses the initial review: quoted software names ('GDX', 'GAMS', 'gamstransfer') in the title and description, added \value documentation to every exported function, and replaced the \dontrun{} examples with self-contained, executable ones. - extract.gdx now uses inherits() for symbol-type checks and reports the offending class in its unknown-symbol-type error (previously referenced an undefined variable). - Updated maintainer email and removed the obsolete gdxrrw copyright holder now that no gdxrrw code remains. Changes in version 1.1.0 Lazy loading by default - gdx(filename) now opens the file in lazy mode by default: only symbol metadata (names, dimensions, domains, descriptions) is read up front, and each symbol's records are fetched on first access via [.gdx / extract(). Pass lazy = FALSE to restore the 1.0.0 behavior (all records loaded at open time). - On large gdx files (e.g. WITCH results with ~4500 symbols), this halves the gdx() open cost: in our benchmark, ~3.7 s lazy vs. ~6.6 s eager. Per-extract cost stays sub-50 ms when records have not been loaded yet, and is essentially free on cache hit. - Internally a second gamstransfer::Container is kept for record reads. Reading symbols into the metadata container is O(symCount) per call because gamstransfer revalidates the existing symbol table; reading into a dedicated empty container is O(1) — ~10 ms vs. ~800 ms per extract on the WITCH gdx. - batch_extract() now performs a single bulk read() per file (pre-loading all requested items) before iterating, which is one C++ round-trip per gdx instead of one per (item, gdx) pair. - New load_records(gdx, symbols = NULL) helper: explicitly batch-load records when you know up front which symbols you'll need. With symbols = NULL it loads everything (equivalent to opening eagerly, but deferrable). - gdx() now does a single-pass describe via Container$getSymbols() instead of five separate list*() calls followed by per-symbol dimension / description vapply — about 2× faster on a gdx with many equations. - all_items() now returns the cached name vectors stored on the gdx object rather than re-querying the container. Behavior note: in lazy mode, accessing the underlying container directly via mygdx$.container[name]$records returns NULL until the symbol has been extracted at least once. Code that bypasses extract / [ and reaches into .container for records should either call load_records() first or open with lazy = FALSE. Domain / class / dimension queries on .container are unaffected. Changes in version 1.0.0 Major change — gamstransfer backend - The package is now backed by gamstransfer, the GDX I/O package maintained by GAMS Software GmbH. No compiled code ships in this package any more (src/ removed). - The high-level API is preserved: gdx(), [.gdx, extract(), all_items(), batch_extract(), write.gdx(), write2.gdx(). Existing user code calling these should not need changes. - write.gdx() no longer shells out to a GAMS process; the removeLST, usetempdir and digits arguments are accepted for compatibility but ignored. compress = TRUE still produces a compressed GDX. - write2.gdx() is now a thin alias of write.gdx() (both use the same fast path). - igdx() and gams() are kept as thin compatibility shims (PATH-based GAMS discovery + system2 runner). The lower-level gdxrrw-shaped exports rgdx, wgdx, gdxInfo, rgdx.param, rgdx.set and rgdx.scalar have been removed. - Behavior change: extracting a sparse parameter no longer densifies the result with explicit zeros. Only entries actually stored in the GDX are returned. (Variables and equations are unaffected.) New options - na = c("drop", "keep", "error") on write.gdx() / write2.gdx() — controls how NA / NaN values in parameter value columns are handled. Defaults to "drop" (legacy v0.7 semantic: silently discarded, GAMS reads 0 for those keys). "keep" preserves them as GAMS NA / undef; "error" stops with an informative message. - dup = c("first", "last", "error") on write.gdx() / write2.gdx() — controls duplicate-key collapsing. Defaults to "first" (legacy write2.gdx / wgdx semantic, which auto-selected in 95% of v0.7 calls). "last" matches the legacy write.gdx GAMS-process path; "error" stops when duplicates are present. A warning fires for both first and last so dropped rows are always audible. Bug fixes - write.gdx() drops default-valued records for free variables (level=0, lower=-Inf, upper=+Inf) to match legacy v0.7 semantic (subset(v, value!=0) for level, subset(v, !is.infinite(value)) for bounds). Downstream tools (notably WITCH's witchtools time-period extension) rely on the absence of zero-level records to back-fill early years from the first non-default record. - gdx() strips the position suffix gamstransfer adds to relaxed-string domain columns (witch13_3 → witch13). Callers look up the bare set name (df$witch13) and previously fell back silently when the suffix was present, which left WITCH parameters un-aggregated. - write.gdx() warns when an index column is double-precision numeric with non-integer content. Catches a common scripting bug where a stray numeric column (e.g. low / high left over from a parquet read) silently becomes an extra UEL-string dimension. Integer-valued doubles (year stored as 1850.0) are still silent. - write.gdx() collapses duplicate set rows the same way as parameter and variable keys. - write.gdx() collapses duplicate index keys with dup = "first" (default) and warns with the dropped-row count. - write.gdx() writes empty variables as a declaration of the right dimension instead of silently dropping them. - write.gdx() handles duplicate index column names (e.g. (*, *, value) from a data.table) by make.unique-ing the records while preserving the original domain reference on the symbol. - write.gdx() no longer leaks set column names as separate symbols in the output GDX (e.g. an explicit set r no longer produced a stray r parameter). - write.gdx() pre-flight checks for NA values in index columns and stops with a clear error instead of letting gamstransfer's C++ layer abort the R session with SIGABRT. - gdx() suppresses the gamstransfer acronym warning emitted at load time for symbols that use the GAMS Acronym facility. Changes in version 0.7.1 - Code cleaning - batch_extract allows now for with extra arguments for extract - Faster write.gdx with variables Changes in version 0.7.0 - Includes gdxrrw 1.0.8 Changes in version 0.6.0 - Faster write gdx when only parameters and/or sets using gdxrrw - Fast write2 gdx function Changes in version 0.5.1 - Can write set with one dimension - Fix writing with sets containing digits with different size - Allows for space and dots in set names when writing gdx Changes in version 0.4.0 - Includes gdxrrw Changes in version 0.3.5 - speed up in extract gdx - gdx compression by default - add some tests - handle empty parameter Changes in version 0.3.4 - add variables in write.gdx (deal with .l, .lo, .up) Changes in version 0.3.3 - add digits in write.gdx to control the precision Changes in version 0.2 - Change license to EPL to comply with gdxrrw - Fix a lot of bugs on the extraction - Add many tests Changes in version 0.1 - first version