![]() |
Birth Generator 1.1.1
Procedural birth date generation for C++23
|
This guide covers every feature of the birth-generator library in detail. For a quick overview, see the README. For the full API reference, run doxygen Doxyfile from the repository root and open doc/api/html/index.html.
dasmig/birthgen.hpp and dasmig/random.hpp into your include path.resources/ folder (containing full/ and/or lite/ subdirectories with their three TSV files) so it is accessible at runtime.-std=c++23.The library ships two dataset tiers:
| Tier | Enum | Countries | Description |
|---|---|---|---|
| lite | dasmig::dataset::lite | ~195 | Sovereign states only |
| full | dasmig::dataset::full | ~235 | All countries and territories (UN WPP coverage) |
Each tier stores three TSV files:
| File | Content |
|---|---|
countries.tsv | ISO codes, name, region, latitude, life expectancy, C-section rate |
age_pyramid.tsv | Population by single year of age (0–100) for male and female |
monthly_births.tsv | Seasonal birth weights by month (latitude-derived) |
On first access the singleton constructor probes these base paths:
| Priority | Base path |
|---|---|
| 1 | resources/ |
| 2 | ../resources/ |
| 3 | birth-generator/resources/ |
It loads lite/ if found, otherwise falls back to full/.
If the country code is not found (e.g., "XX"), get_birth() throws std::invalid_argument.
Fix the biological sex instead of drawing it from the M:F ratio:
Fix the birth year instead of drawing from the age pyramid. Age is derived as ref_year − year and clamped to [0, 100]:
Fix both sex and year — only month, day, weekday, LE, and cohort are randomised:
Constrain the age to an inclusive range. The age is rejection-sampled from the country's age pyramid within the bounds:
Throws std::invalid_argument if min > max.
Every dasmig::birth object exposes these fields:
| Field | Type | Description |
|---|---|---|
country_code | std::string | ISO 3166-1 alpha-2 code |
year | std::uint16_t | Birth year |
month | std::uint8_t | Birth month (1–12) |
day | std::uint8_t | Birth day (1–31) |
age | std::uint8_t | Age in completed years |
bio_sex | dasmig::sex | sex::male or sex::female |
weekday | std::uint8_t | Day of week (0=Sun, 1=Mon, …, 6=Sat) |
le_remaining | double | Estimated years of life remaining |
cohort | std::string | Generational cohort label |
| Cohort | Birth years |
|---|---|
| Greatest Generation | ≤ 1927 |
| Silent Generation | 1928–1945 |
| Baby Boomer | 1946–1964 |
| Generation X | 1965–1980 |
| Millennial | 1981–1996 |
| Generation Z | 1997–2012 |
| Generation Alpha | ≥ 2013 |
Pass an ISO 3166-1 alpha-2 code to generate a birth from a specific country:
The age pyramid, life expectancy, seasonal model, and C-section rate are all country-specific.
By default, countries are selected proportional to their total population. This means births from China, India, and the United States are far more common than births from small nations.
Switch to equal-probability country selection:
Every birth stores the random seed used to generate it:
Construct independent instances for isolation:
Useful when embedding inside other generators or when different threads need independent generators.
Each get_birth() call runs the following pipeline:
sex parameter is provided).year_t, or rejection-sampled within an age_range).reference_year − age (reference year = current year).csection_rate × 0.5 (up to 3 retries).std::chrono::weekday from the final date.max(0, LE_at_birth − age) using sex-specific period life expectancy from UN WPP 2024.The scripts/prepare_births.py script downloads and processes data from three sources:
It produces three TSV files per tier:
Regenerate with:
Downloaded files are cached in scripts/.cache/ to avoid repeated downloads.
The random engine inside each bthg instance is not thread-safe. If you call get_birth() from multiple threads, either:
bthg instance per thread, orThe singleton bthg::instance() returns a single shared instance, so concurrent access must be synchronized.
| Error | Cause |
|---|---|
std::runtime_error("No birth data loaded. Call load() first.") | Called get_birth() before any load() and auto-probe found nothing. |
std::invalid_argument("Unknown country code: XX") | The country code passed to get_birth("XX") is not in the loaded dataset. |
std::invalid_argument("age_range: min must be <= max") | Passed an age_range where min > max. |