Rename IEEE 754 from_f64_to_u{16,32} functions
diff --git a/internal/cgen/base/floatconv-submodule-code.c b/internal/cgen/base/floatconv-submodule-code.c
index 0e9f8a2..603d180 100644
--- a/internal/cgen/base/floatconv-submodule-code.c
+++ b/internal/cgen/base/floatconv-submodule-code.c
@@ -17,7 +17,7 @@
 // ---------------- IEEE 754 Floating Point
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16  //
-wuffs_base__ieee_754_bit_representation__from_f64_to_u16(double f) {
+wuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f) {
   uint64_t u = 0;
   if (sizeof(uint64_t) == sizeof(double)) {
     memcpy(&u, &f, sizeof(uint64_t));
@@ -81,7 +81,7 @@
 }
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32  //
-wuffs_base__ieee_754_bit_representation__from_f64_to_u32(double f) {
+wuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f) {
   uint64_t u = 0;
   if (sizeof(uint64_t) == sizeof(double)) {
     memcpy(&u, &f, sizeof(uint64_t));
diff --git a/internal/cgen/base/strconv-public.h b/internal/cgen/base/strconv-public.h
index 2e2215f..8fce7a1 100644
--- a/internal/cgen/base/strconv-public.h
+++ b/internal/cgen/base/strconv-public.h
@@ -108,12 +108,18 @@
 //  - -inf and 0xFC00, 0xFF80_0000 or 0xFFF0_0000_0000_0000.
 //
 // Converting from f64 to shorter formats (f16 or f32, represented in C as
-// uint16_t and uint32_t) may be lossy. Converting finite numbers truncate,
-// producing equal or smaller (closer-to-zero) finite numbers. Converting
-// infinities or NaNs produces infinities or NaNs and always report no loss,
-// even though there a multiple NaN representations so that round-tripping a
-// f64 NaN may produce a different 64 bits. Nonetheless, a NaN's "quiet vs
-// signaling" bit is preserved.
+// uint16_t and uint32_t) may be lossy. Such functions have names that look
+// like etc_truncate, as converting finite numbers produce equal or smaller
+// (closer-to-zero) finite numbers. For example, 1048576.0 is a perfectly valid
+// f64 number, but converting it to a f16 (with truncation) produces 65504.0,
+// the largest finite f16 number. Truncating a f64-typed value d to f32 does
+// not always produce the same result as the C-style cast ((float)d), as
+// casting can convert from finite numbers to infinite ones.
+//
+// Converting infinities or NaNs produces infinities or NaNs and always report
+// no loss, even though there a multiple NaN representations so that round-
+// tripping a f64-typed NaN may produce a different 64 bits. Nonetheless, the
+// etc_truncate functions preserve a NaN's "quiet vs signaling" bit.
 //
 // See https://en.wikipedia.org/wiki/Double-precision_floating-point_format
 
@@ -128,10 +134,10 @@
 } wuffs_base__lossy_value_u32;
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16  //
-wuffs_base__ieee_754_bit_representation__from_f64_to_u16(double f);
+wuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f);
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32  //
-wuffs_base__ieee_754_bit_representation__from_f64_to_u32(double f);
+wuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f);
 
 static inline uint64_t  //
 wuffs_base__ieee_754_bit_representation__from_f64_to_u64(double f) {
diff --git a/internal/cgen/data/data.go b/internal/cgen/data/data.go
index 6c9ece2..46320e0 100644
--- a/internal/cgen/data/data.go
+++ b/internal/cgen/data/data.go
@@ -29,11 +29,11 @@
 	""
 
 const BaseFloatConvSubmoduleCodeC = "" +
-	"// ---------------- IEEE 754 Floating Point\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16  //\nwuffs_base__ieee_754_bit_representation__from_f64_to_u16(double f) {\n  uint64_t u = 0;\n  if (sizeof(uint64_t) == sizeof(double)) {\n    memcpy(&u, &f, sizeof(uint64_t));\n  }\n  uint16_t neg = ((uint16_t)(u >> 63)) << 15;\n  u &= 0x7FFFFFFFFFFFFFFF;\n  uint64_t exp = u >> 52;\n  uint64_t man = u & 0x000FFFFFFFFFFFFF;\n\n  if (exp == 0x7FF) {\n    if (man == 0) {  // Infinity.\n      wuffs_base__lossy_value_u16 ret;\n      ret.value = neg | 0x7C00;\n      ret.lossy = false;\n      return ret;\n    }\n    // NaN. Shift the 52 mantissa bits to 10 mantissa bits, keeping the most\n    // significant mantissa bit (quiet vs signaling NaNs). Also set the low 9\n    // bits of ret.value so that the 10-bit mantissa is non-zero.\n    wuffs_base__lossy_value_u16 ret;\n    ret.value = neg | 0x7DFF | ((uint16_t)(man >> 42));\n    ret.lossy = false;\n    return ret;\n\n  } else if (exp > 0x40E) {  // Truncate to the largest finite f16.\n    wuffs_" +
-	"base__lossy_value_u16 ret;\n    ret.value = neg | 0x7BFF;\n    ret.lossy = true;\n    return ret;\n\n  } else if (exp <= 0x3E6) {  // Truncate to zero.\n    wuffs_base__lossy_value_u16 ret;\n    ret.value = neg;\n    ret.lossy = (u != 0);\n    return ret;\n\n  } else if (exp <= 0x3F0) {  // Normal f64, subnormal f16.\n    // Convert from a 53-bit mantissa (after realizing the implicit bit) to a\n    // 10-bit mantissa and then adjust for the exponent.\n    man |= 0x0010000000000000;\n    uint32_t shift = 1051 - exp;  // 1051 = 0x3F0 + 53 - 10.\n    uint64_t shifted_man = man >> shift;\n    wuffs_base__lossy_value_u16 ret;\n    ret.value = neg | ((uint16_t)shifted_man);\n    ret.lossy = (shifted_man << shift) != man;\n    return ret;\n  }\n\n  // Normal f64, normal f16.\n\n  // Re-bias from 1023 to 15 and shift above f16's 10 mantissa bits.\n  exp = (exp - 1008) << 10;  // 1008 = 1023 - 15 = 0x3FF - 0xF.\n\n  // Convert from a 52-bit mantissa (excluding the implicit bit) to a 10-bit\n  // mantissa (again excluding the implicit bit). We lo" +
-	"se some information if\n  // any of the bottom 42 bits are non-zero.\n  wuffs_base__lossy_value_u16 ret;\n  ret.value = neg | ((uint16_t)exp) | ((uint16_t)(man >> 42));\n  ret.lossy = (man << 22) != 0;\n  return ret;\n}\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32  //\nwuffs_base__ieee_754_bit_representation__from_f64_to_u32(double f) {\n  uint64_t u = 0;\n  if (sizeof(uint64_t) == sizeof(double)) {\n    memcpy(&u, &f, sizeof(uint64_t));\n  }\n  uint32_t neg = ((uint32_t)(u >> 63)) << 31;\n  u &= 0x7FFFFFFFFFFFFFFF;\n  uint64_t exp = u >> 52;\n  uint64_t man = u & 0x000FFFFFFFFFFFFF;\n\n  if (exp == 0x7FF) {\n    if (man == 0) {  // Infinity.\n      wuffs_base__lossy_value_u32 ret;\n      ret.value = neg | 0x7F800000;\n      ret.lossy = false;\n      return ret;\n    }\n    // NaN. Shift the 52 mantissa bits to 23 mantissa bits, keeping the most\n    // significant mantissa bit (quiet vs signaling NaNs). Also set the low 22\n    // bits of ret.value so that the 23-bit mantissa is non-zero.\n    wuffs_base__lossy_value_u32 ret;" +
-	"\n    ret.value = neg | 0x7FBFFFFF | ((uint32_t)(man >> 29));\n    ret.lossy = false;\n    return ret;\n\n  } else if (exp > 0x47E) {  // Truncate to the largest finite f32.\n    wuffs_base__lossy_value_u32 ret;\n    ret.value = neg | 0x7F7FFFFF;\n    ret.lossy = true;\n    return ret;\n\n  } else if (exp <= 0x369) {  // Truncate to zero.\n    wuffs_base__lossy_value_u32 ret;\n    ret.value = neg;\n    ret.lossy = (u != 0);\n    return ret;\n\n  } else if (exp <= 0x380) {  // Normal f64, subnormal f32.\n    // Convert from a 53-bit mantissa (after realizing the implicit bit) to a\n    // 23-bit mantissa and then adjust for the exponent.\n    man |= 0x0010000000000000;\n    uint32_t shift = 926 - exp;  // 926 = 0x380 + 53 - 23.\n    uint64_t shifted_man = man >> shift;\n    wuffs_base__lossy_value_u32 ret;\n    ret.value = neg | ((uint32_t)shifted_man);\n    ret.lossy = (shifted_man << shift) != man;\n    return ret;\n  }\n\n  // Normal f64, normal f32.\n\n  // Re-bias from 1023 to 127 and shift above f32's 23 mantissa bits.\n  exp = (exp - " +
-	"896) << 23;  // 896 = 1023 - 127 = 0x3FF - 0x7F.\n\n  // Convert from a 52-bit mantissa (excluding the implicit bit) to a 23-bit\n  // mantissa (again excluding the implicit bit). We lose some information if\n  // any of the bottom 29 bits are non-zero.\n  wuffs_base__lossy_value_u32 ret;\n  ret.value = neg | ((uint32_t)exp) | ((uint32_t)(man >> 29));\n  ret.lossy = (man << 35) != 0;\n  return ret;\n}\n\n" +
+	"// ---------------- IEEE 754 Floating Point\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16  //\nwuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f) {\n  uint64_t u = 0;\n  if (sizeof(uint64_t) == sizeof(double)) {\n    memcpy(&u, &f, sizeof(uint64_t));\n  }\n  uint16_t neg = ((uint16_t)(u >> 63)) << 15;\n  u &= 0x7FFFFFFFFFFFFFFF;\n  uint64_t exp = u >> 52;\n  uint64_t man = u & 0x000FFFFFFFFFFFFF;\n\n  if (exp == 0x7FF) {\n    if (man == 0) {  // Infinity.\n      wuffs_base__lossy_value_u16 ret;\n      ret.value = neg | 0x7C00;\n      ret.lossy = false;\n      return ret;\n    }\n    // NaN. Shift the 52 mantissa bits to 10 mantissa bits, keeping the most\n    // significant mantissa bit (quiet vs signaling NaNs). Also set the low 9\n    // bits of ret.value so that the 10-bit mantissa is non-zero.\n    wuffs_base__lossy_value_u16 ret;\n    ret.value = neg | 0x7DFF | ((uint16_t)(man >> 42));\n    ret.lossy = false;\n    return ret;\n\n  } else if (exp > 0x40E) {  // Truncate to the largest finite f16.\n " +
+	"   wuffs_base__lossy_value_u16 ret;\n    ret.value = neg | 0x7BFF;\n    ret.lossy = true;\n    return ret;\n\n  } else if (exp <= 0x3E6) {  // Truncate to zero.\n    wuffs_base__lossy_value_u16 ret;\n    ret.value = neg;\n    ret.lossy = (u != 0);\n    return ret;\n\n  } else if (exp <= 0x3F0) {  // Normal f64, subnormal f16.\n    // Convert from a 53-bit mantissa (after realizing the implicit bit) to a\n    // 10-bit mantissa and then adjust for the exponent.\n    man |= 0x0010000000000000;\n    uint32_t shift = 1051 - exp;  // 1051 = 0x3F0 + 53 - 10.\n    uint64_t shifted_man = man >> shift;\n    wuffs_base__lossy_value_u16 ret;\n    ret.value = neg | ((uint16_t)shifted_man);\n    ret.lossy = (shifted_man << shift) != man;\n    return ret;\n  }\n\n  // Normal f64, normal f16.\n\n  // Re-bias from 1023 to 15 and shift above f16's 10 mantissa bits.\n  exp = (exp - 1008) << 10;  // 1008 = 1023 - 15 = 0x3FF - 0xF.\n\n  // Convert from a 52-bit mantissa (excluding the implicit bit) to a 10-bit\n  // mantissa (again excluding the implicit bi" +
+	"t). We lose some information if\n  // any of the bottom 42 bits are non-zero.\n  wuffs_base__lossy_value_u16 ret;\n  ret.value = neg | ((uint16_t)exp) | ((uint16_t)(man >> 42));\n  ret.lossy = (man << 22) != 0;\n  return ret;\n}\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32  //\nwuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f) {\n  uint64_t u = 0;\n  if (sizeof(uint64_t) == sizeof(double)) {\n    memcpy(&u, &f, sizeof(uint64_t));\n  }\n  uint32_t neg = ((uint32_t)(u >> 63)) << 31;\n  u &= 0x7FFFFFFFFFFFFFFF;\n  uint64_t exp = u >> 52;\n  uint64_t man = u & 0x000FFFFFFFFFFFFF;\n\n  if (exp == 0x7FF) {\n    if (man == 0) {  // Infinity.\n      wuffs_base__lossy_value_u32 ret;\n      ret.value = neg | 0x7F800000;\n      ret.lossy = false;\n      return ret;\n    }\n    // NaN. Shift the 52 mantissa bits to 23 mantissa bits, keeping the most\n    // significant mantissa bit (quiet vs signaling NaNs). Also set the low 22\n    // bits of ret.value so that the 23-bit mantissa is non-zero.\n    wuffs_base__lo" +
+	"ssy_value_u32 ret;\n    ret.value = neg | 0x7FBFFFFF | ((uint32_t)(man >> 29));\n    ret.lossy = false;\n    return ret;\n\n  } else if (exp > 0x47E) {  // Truncate to the largest finite f32.\n    wuffs_base__lossy_value_u32 ret;\n    ret.value = neg | 0x7F7FFFFF;\n    ret.lossy = true;\n    return ret;\n\n  } else if (exp <= 0x369) {  // Truncate to zero.\n    wuffs_base__lossy_value_u32 ret;\n    ret.value = neg;\n    ret.lossy = (u != 0);\n    return ret;\n\n  } else if (exp <= 0x380) {  // Normal f64, subnormal f32.\n    // Convert from a 53-bit mantissa (after realizing the implicit bit) to a\n    // 23-bit mantissa and then adjust for the exponent.\n    man |= 0x0010000000000000;\n    uint32_t shift = 926 - exp;  // 926 = 0x380 + 53 - 23.\n    uint64_t shifted_man = man >> shift;\n    wuffs_base__lossy_value_u32 ret;\n    ret.value = neg | ((uint32_t)shifted_man);\n    ret.lossy = (shifted_man << shift) != man;\n    return ret;\n  }\n\n  // Normal f64, normal f32.\n\n  // Re-bias from 1023 to 127 and shift above f32's 23 mantissa bit" +
+	"s.\n  exp = (exp - 896) << 23;  // 896 = 1023 - 127 = 0x3FF - 0x7F.\n\n  // Convert from a 52-bit mantissa (excluding the implicit bit) to a 23-bit\n  // mantissa (again excluding the implicit bit). We lose some information if\n  // any of the bottom 29 bits are non-zero.\n  wuffs_base__lossy_value_u32 ret;\n  ret.value = neg | ((uint32_t)exp) | ((uint32_t)(man >> 29));\n  ret.lossy = (man << 35) != 0;\n  return ret;\n}\n\n" +
 	"" +
 	"// --------\n\n#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE 2047\n#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION 800\n\n// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL is the largest N\n// such that ((10 << N) < (1 << 64)).\n#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL 60\n\n// wuffs_base__private_implementation__high_prec_dec (abbreviated as HPD) is a\n// fixed precision floating point decimal number, augmented with ±infinity\n// values, but it cannot represent NaN (Not a Number).\n//\n// \"High precision\" means that the mantissa holds 800 decimal digits. 800 is\n// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION.\n//\n// An HPD isn't for general purpose arithmetic, only for conversions to and\n// from IEEE 754 double-precision floating point, where the largest and\n// smallest positive, finite values are approximately 1.8e+308 and 4.9e-324.\n// HPD exponents above +2047 mean infinity, below -2047 mean zero. The ±2047\n// bounds are further a" +
 	"way from zero than ±(324 + 800), where 800 and 2047 is\n// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION and\n// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE.\n//\n// digits[.. num_digits] are the number's digits in big-endian order. The\n// uint8_t values are in the range [0 ..= 9], not ['0' ..= '9'], where e.g. '7'\n// is the ASCII value 0x37.\n//\n// decimal_point is the index (within digits) of the decimal point. It may be\n// negative or be larger than num_digits, in which case the explicit digits are\n// padded with implicit zeroes.\n//\n// For example, if num_digits is 3 and digits is \"\\x07\\x08\\x09\":\n//   - A decimal_point of -2 means \".00789\"\n//   - A decimal_point of -1 means \".0789\"\n//   - A decimal_point of +0 means \".789\"\n//   - A decimal_point of +1 means \"7.89\"\n//   - A decimal_point of +2 means \"78.9\"\n//   - A decimal_point of +3 means \"789.\"\n//   - A decimal_point of +4 means \"7890.\"\n//   - A decimal_point of +5 means \"78900.\"\n//\n// As above, a decimal_point higher than +2047" +
@@ -521,10 +521,10 @@
 	"XX__DECIMAL_SEPARATOR_IS_A_COMMA \\\n  ((uint32_t)0x00001000)\n\n// WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ETC means whether to never\n// (EXPONENT_ABSENT, equivalent to printf's \"%f\") or to always\n// (EXPONENT_PRESENT, equivalent to printf's \"%e\") render a floating point\n// number as \"1.23e+05\" instead of \"123000\".\n//\n// Having both bits set is the same has having neither bit set, where the\n// notation used depends on whether the exponent is sufficiently large: \"0.5\"\n// is preferred over \"5e-01\" but \"5e-09\" is preferred over \"0.000000005\".\n#define WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT ((uint32_t)0x00002000)\n#define WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT ((uint32_t)0x00004000)\n\n// WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION means to render the\n// smallest number of digits so that parsing the resultant string will recover\n// the same double-precision floating point number.\n//\n// For example, double-precision cannot distinguish between 0.3 and\n// 0.2999999999999999888977697537484345957636" +
 	"83319091796875, so when this bit\n// is set, rendering the latter will produce \"0.3\" but rendering\n// 0.3000000000000000444089209850062616169452667236328125 will produce\n// \"0.30000000000000004\".\n#define WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION \\\n  ((uint32_t)0x00008000)\n\n" +
 	"" +
-	"// ---------------- IEEE 754 Floating Point\n\n// wuffs_base__ieee_754_bit_representation__etc converts between a double\n// precision numerical value and its IEEE 754 representations:\n//   - 16-bit: 1 sign bit,  5 exponent bits, 10 explicit significand bits.\n//   - 32-bit: 1 sign bit,  8 exponent bits, 23 explicit significand bits.\n//   - 64-bit: 1 sign bit, 11 exponent bits, 52 explicit significand bits.\n//\n// For example, it converts between:\n//  - +1.0 and 0x3C00, 0x3F80_0000 or 0x3FF0_0000_0000_0000.\n//  - +5.5 and 0x4580, 0x40B0_0000 or 0x4016_0000_0000_0000.\n//  - -inf and 0xFC00, 0xFF80_0000 or 0xFFF0_0000_0000_0000.\n//\n// Converting from f64 to shorter formats (f16 or f32, represented in C as\n// uint16_t and uint32_t) may be lossy. Converting finite numbers truncate,\n// producing equal or smaller (closer-to-zero) finite numbers. Converting\n// infinities or NaNs produces infinities or NaNs and always report no loss,\n// even though there a multiple NaN representations so that round-tripping a\n// f64 NaN m" +
-	"ay produce a different 64 bits. Nonetheless, a NaN's \"quiet vs\n// signaling\" bit is preserved.\n//\n// See https://en.wikipedia.org/wiki/Double-precision_floating-point_format\n\ntypedef struct {\n  uint16_t value;\n  bool lossy;\n} wuffs_base__lossy_value_u16;\n\ntypedef struct {\n  uint32_t value;\n  bool lossy;\n} wuffs_base__lossy_value_u32;\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16  //\nwuffs_base__ieee_754_bit_representation__from_f64_to_u16(double f);\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32  //\nwuffs_base__ieee_754_bit_representation__from_f64_to_u32(double f);\n\nstatic inline uint64_t  //\nwuffs_base__ieee_754_bit_representation__from_f64_to_u64(double f) {\n  uint64_t u = 0;\n  if (sizeof(uint64_t) == sizeof(double)) {\n    memcpy(&u, &f, sizeof(uint64_t));\n  }\n  return u;\n}\n\nstatic inline double  //\nwuffs_base__ieee_754_bit_representation__from_u16_to_f64(uint16_t u) {\n  uint64_t v = ((uint64_t)(u & 0x8000)) << 48;\n\n  do {\n    uint64_t exp = (u >> 10) & 0x1F;\n    uint64_t man = u & 0x3FF;\n  " +
-	"  if (exp == 0x1F) {  // Infinity or NaN.\n      exp = 2047;\n    } else if (exp != 0) {  // Normal.\n      exp += 1008;          // 1008 = 1023 - 15, the difference in biases.\n    } else if (man != 0) {  // Subnormal but non-zero.\n      uint32_t clz = wuffs_base__count_leading_zeroes_u64(man);\n      exp = 1062 - clz;  // 1062 = 1008 + 64 - 10.\n      man = 0x3FF & (man << (clz - 53));\n    } else {  // Zero.\n      break;\n    }\n    v |= (exp << 52) | (man << 42);\n  } while (0);\n\n  double f = 0;\n  if (sizeof(uint64_t) == sizeof(double)) {\n    memcpy(&f, &v, sizeof(uint64_t));\n  }\n  return f;\n}\n\nstatic inline double  //\nwuffs_base__ieee_754_bit_representation__from_u32_to_f64(uint32_t u) {\n  float f = 0;\n  if (sizeof(uint32_t) == sizeof(float)) {\n    memcpy(&f, &u, sizeof(uint32_t));\n  }\n  return (double)f;\n}\n\nstatic inline double  //\nwuffs_base__ieee_754_bit_representation__from_u64_to_f64(uint64_t u) {\n  double f = 0;\n  if (sizeof(uint64_t) == sizeof(double)) {\n    memcpy(&f, &u, sizeof(uint64_t));\n  }\n  return f;" +
-	"\n}\n\n" +
+	"// ---------------- IEEE 754 Floating Point\n\n// wuffs_base__ieee_754_bit_representation__etc converts between a double\n// precision numerical value and its IEEE 754 representations:\n//   - 16-bit: 1 sign bit,  5 exponent bits, 10 explicit significand bits.\n//   - 32-bit: 1 sign bit,  8 exponent bits, 23 explicit significand bits.\n//   - 64-bit: 1 sign bit, 11 exponent bits, 52 explicit significand bits.\n//\n// For example, it converts between:\n//  - +1.0 and 0x3C00, 0x3F80_0000 or 0x3FF0_0000_0000_0000.\n//  - +5.5 and 0x4580, 0x40B0_0000 or 0x4016_0000_0000_0000.\n//  - -inf and 0xFC00, 0xFF80_0000 or 0xFFF0_0000_0000_0000.\n//\n// Converting from f64 to shorter formats (f16 or f32, represented in C as\n// uint16_t and uint32_t) may be lossy. Such functions have names that look\n// like etc_truncate, as converting finite numbers produce equal or smaller\n// (closer-to-zero) finite numbers. For example, 1048576.0 is a perfectly valid\n// f64 number, but converting it to a f16 (with truncation) produces 65504.0,\n// the" +
+	" largest finite f16 number. Truncating a f64-typed value d to f32 does\n// not always produce the same result as the C-style cast ((float)d), as\n// casting can convert from finite numbers to infinite ones.\n//\n// Converting infinities or NaNs produces infinities or NaNs and always report\n// no loss, even though there a multiple NaN representations so that round-\n// tripping a f64-typed NaN may produce a different 64 bits. Nonetheless, the\n// etc_truncate functions preserve a NaN's \"quiet vs signaling\" bit.\n//\n// See https://en.wikipedia.org/wiki/Double-precision_floating-point_format\n\ntypedef struct {\n  uint16_t value;\n  bool lossy;\n} wuffs_base__lossy_value_u16;\n\ntypedef struct {\n  uint32_t value;\n  bool lossy;\n} wuffs_base__lossy_value_u32;\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16  //\nwuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f);\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32  //\nwuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f);\n\nst" +
+	"atic inline uint64_t  //\nwuffs_base__ieee_754_bit_representation__from_f64_to_u64(double f) {\n  uint64_t u = 0;\n  if (sizeof(uint64_t) == sizeof(double)) {\n    memcpy(&u, &f, sizeof(uint64_t));\n  }\n  return u;\n}\n\nstatic inline double  //\nwuffs_base__ieee_754_bit_representation__from_u16_to_f64(uint16_t u) {\n  uint64_t v = ((uint64_t)(u & 0x8000)) << 48;\n\n  do {\n    uint64_t exp = (u >> 10) & 0x1F;\n    uint64_t man = u & 0x3FF;\n    if (exp == 0x1F) {  // Infinity or NaN.\n      exp = 2047;\n    } else if (exp != 0) {  // Normal.\n      exp += 1008;          // 1008 = 1023 - 15, the difference in biases.\n    } else if (man != 0) {  // Subnormal but non-zero.\n      uint32_t clz = wuffs_base__count_leading_zeroes_u64(man);\n      exp = 1062 - clz;  // 1062 = 1008 + 64 - 10.\n      man = 0x3FF & (man << (clz - 53));\n    } else {  // Zero.\n      break;\n    }\n    v |= (exp << 52) | (man << 42);\n  } while (0);\n\n  double f = 0;\n  if (sizeof(uint64_t) == sizeof(double)) {\n    memcpy(&f, &v, sizeof(uint64_t));\n  }\n  return f" +
+	";\n}\n\nstatic inline double  //\nwuffs_base__ieee_754_bit_representation__from_u32_to_f64(uint32_t u) {\n  float f = 0;\n  if (sizeof(uint32_t) == sizeof(float)) {\n    memcpy(&f, &u, sizeof(uint32_t));\n  }\n  return (double)f;\n}\n\nstatic inline double  //\nwuffs_base__ieee_754_bit_representation__from_u64_to_f64(uint64_t u) {\n  double f = 0;\n  if (sizeof(uint64_t) == sizeof(double)) {\n    memcpy(&f, &u, sizeof(uint64_t));\n  }\n  return f;\n}\n\n" +
 	"" +
 	"// ---------------- Parsing and Rendering Numbers\n\n// wuffs_base__parse_number_f64 parses the floating point number in s. For\n// example, if s contains the bytes \"1.5\" then it will return the double 1.5.\n//\n// It returns an error if s does not contain a floating point number.\n//\n// It does not necessarily return an error if the conversion is lossy, e.g. if\n// s is \"0.3\", which double-precision floating point cannot represent exactly.\n//\n// Similarly, the returned value may be infinite (and no error returned) even\n// if s was not \"inf\", when the input is nominally finite but sufficiently\n// larger than DBL_MAX, about 1.8e+308.\n//\n// It is similar to the C standard library's strtod function, but:\n//  - Errors are returned in-band (in a result type), not out-of-band (errno).\n//  - It takes a slice (a pointer and length), not a NUL-terminated C string.\n//  - It does not take an optional endptr argument. It does not allow a partial\n//    parse: it returns an error unless all of s is consumed.\n//  - It does not all" +
 	"ow whitespace, leading or otherwise.\n//  - It does not allow hexadecimal floating point numbers.\n//  - It is not affected by i18n / l10n settings such as environment variables.\n//\n// The options argument can change these, but by default, it:\n//  - Allows \"inf\", \"+Infinity\" and \"-NAN\", case insensitive. Similarly,\n//    without an explicit opt-out, it would successfully parse \"1e999\" as\n//    infinity, even though it overflows double-precision floating point.\n//  - Rejects underscores. With an explicit opt-in, \"_3.141_592\" would\n//    successfully parse as an approximation to π.\n//  - Rejects unnecessary leading zeroes: \"00\", \"0644\" and \"00.7\".\n//  - Uses a dot '1.5' instead of a comma '1,5' for the decimal separator.\n//\n// For modular builds that divide the base module into sub-modules, using this\n// function requires the WUFFS_CONFIG__MODULE__BASE__FLOATCONV sub-module, not\n// just WUFFS_CONFIG__MODULE__BASE__CORE.\nWUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64  //\nwuffs_base__parse_number_f64(wuffs_base__" +
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index cfa53e5..7a6e37f 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -4027,12 +4027,18 @@
 //  - -inf and 0xFC00, 0xFF80_0000 or 0xFFF0_0000_0000_0000.
 //
 // Converting from f64 to shorter formats (f16 or f32, represented in C as
-// uint16_t and uint32_t) may be lossy. Converting finite numbers truncate,
-// producing equal or smaller (closer-to-zero) finite numbers. Converting
-// infinities or NaNs produces infinities or NaNs and always report no loss,
-// even though there a multiple NaN representations so that round-tripping a
-// f64 NaN may produce a different 64 bits. Nonetheless, a NaN's "quiet vs
-// signaling" bit is preserved.
+// uint16_t and uint32_t) may be lossy. Such functions have names that look
+// like etc_truncate, as converting finite numbers produce equal or smaller
+// (closer-to-zero) finite numbers. For example, 1048576.0 is a perfectly valid
+// f64 number, but converting it to a f16 (with truncation) produces 65504.0,
+// the largest finite f16 number. Truncating a f64-typed value d to f32 does
+// not always produce the same result as the C-style cast ((float)d), as
+// casting can convert from finite numbers to infinite ones.
+//
+// Converting infinities or NaNs produces infinities or NaNs and always report
+// no loss, even though there a multiple NaN representations so that round-
+// tripping a f64-typed NaN may produce a different 64 bits. Nonetheless, the
+// etc_truncate functions preserve a NaN's "quiet vs signaling" bit.
 //
 // See https://en.wikipedia.org/wiki/Double-precision_floating-point_format
 
@@ -4047,10 +4053,10 @@
 } wuffs_base__lossy_value_u32;
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16  //
-wuffs_base__ieee_754_bit_representation__from_f64_to_u16(double f);
+wuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f);
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32  //
-wuffs_base__ieee_754_bit_representation__from_f64_to_u32(double f);
+wuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f);
 
 static inline uint64_t  //
 wuffs_base__ieee_754_bit_representation__from_f64_to_u64(double f) {
@@ -9959,7 +9965,7 @@
 // ---------------- IEEE 754 Floating Point
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16  //
-wuffs_base__ieee_754_bit_representation__from_f64_to_u16(double f) {
+wuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f) {
   uint64_t u = 0;
   if (sizeof(uint64_t) == sizeof(double)) {
     memcpy(&u, &f, sizeof(uint64_t));
@@ -10023,7 +10029,7 @@
 }
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32  //
-wuffs_base__ieee_754_bit_representation__from_f64_to_u32(double f) {
+wuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f) {
   uint64_t u = 0;
   if (sizeof(uint64_t) == sizeof(double)) {
     memcpy(&u, &f, sizeof(uint64_t));
diff --git a/test/c/std/json.c b/test/c/std/json.c
index 7385ae5..9f6101d 100644
--- a/test/c/std/json.c
+++ b/test/c/std/json.c
@@ -526,7 +526,7 @@
         continue;
       }
       wuffs_base__lossy_value_u16 lv =
-          wuffs_base__ieee_754_bit_representation__from_f64_to_u16(
+          wuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(
               wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
                   want_u64 ^ ((uint64_t)noise)));
       if (lv.value != test_cases[tc].u16_bits) {
@@ -648,7 +648,7 @@
         continue;
       }
       wuffs_base__lossy_value_u32 lv =
-          wuffs_base__ieee_754_bit_representation__from_f64_to_u32(
+          wuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(
               wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
                   want_u64 ^ ((uint64_t)noise)));
       if (lv.value != test_cases[tc].u32_bits) {