Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions library/core/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@ optimize_for_size = []
# Make `RefCell` store additional debugging information, which is printed out when
# a borrow error occurs
debug_refcell = []
llvm_enzyme = []

[lints.rust.unexpected_cfgs]
level = "warn"
Expand All@@ -38,4 +39,6 @@ check-cfg = [
'cfg(target_has_reliable_f16_math)',
'cfg(target_has_reliable_f128)',
'cfg(target_has_reliable_f128_math)',
'cfg(llvm_enzyme)',

]
103 changes: 103 additions & 0 deletions library/core/src/macros/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
/// indirect input arguments. It can also be used on a scalar float return value.
/// If used on a return value, the generated function will return a tuple of two float scalars.
/// If used on an input argument, a new shadow argument of the same type will be created,
/// directly following the original argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
/// // When seeding both arguments at once the tangent return is the sum of both.
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
///
/// let mut out = 0.0;
/// let mut dout = 0.0;
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
/// // (out, dout) == (400.0, -400.0)
/// }
/// ```
///
/// We might want to track how one input float affects one or more output floats. In this case,
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
/// more efficient if we have more output floats marked as `Dual` than input floats.
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand All@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
///
/// `Active` can be used for float scalar values.
/// If used on an input, a new float will be appended to the return tuple of the generated
/// function. If the function returns a float scalar, `Active` can be used for the return as
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
///
/// `Duplicated` can be used on references, raw pointers, or other indirect input
/// arguments. It creates a new shadow argument of the same type, following the original argument.
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
/// let mut output2 = 0.0;
/// let mut seed = 1.0;
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
/// }
/// ```
///
///
/// We often want to track how one or more input floats affect one output float. This output can
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
/// shadow of the outputs ("seed") will be reset to zero.
/// If the function has more than one output float marked as active or duplicated, users might want to
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a bit unclear to me how the 1.0 and 0.0 are used to specify the partial derivatives. I would assume the output given 1.0 has it's derivative evaluated and the one 0.0 not, but I think it would be good to be explicit in the docs.

/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
/// inputs.
/// Reverse mode is generally more efficient if we have more active/duplicated input than
/// output floats.
///
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand Down
1 change: 1 addition & 0 deletions library/std/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
# a borrow error occurs
debug_refcell = ["core/debug_refcell"]

llvm_enzyme = ["core/llvm_enzyme"]

# Enable std_detect features:
std_detect_file_io = ["std_detect/std_detect_file_io"]
Expand Down
1 change: 1 addition & 0 deletions library/sysroot/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
std_detect_file_io = ["std/std_detect_file_io"]
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
windows_raw_dylib = ["std/windows_raw_dylib"]
llvm_enzyme = ["std/llvm_enzyme"]
4 changes: 4 additions & 0 deletions src/bootstrap/src/lib.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -846,6 +846,10 @@ impl Build {
features.insert("compiler-builtins-mem");
}

if self.config.llvm_enzyme {
features.insert("llvm_enzyme");
}

features.into_iter().collect::<Vec<_>>().join(" ")
}

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions library/core/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@ optimize_for_size = []
# Make `RefCell` store additional debugging information, which is printed out when
# a borrow error occurs
debug_refcell = []
llvm_enzyme = []

[lints.rust.unexpected_cfgs]
level = "warn"
Expand All@@ -38,4 +39,6 @@ check-cfg = [
'cfg(target_has_reliable_f16_math)',
'cfg(target_has_reliable_f128)',
'cfg(target_has_reliable_f128_math)',
'cfg(llvm_enzyme)',

]
103 changes: 103 additions & 0 deletions library/core/src/macros/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
/// indirect input arguments. It can also be used on a scalar float return value.
/// If used on a return value, the generated function will return a tuple of two float scalars.
/// If used on an input argument, a new shadow argument of the same type will be created,
/// directly following the original argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
/// // When seeding both arguments at once the tangent return is the sum of both.
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
///
/// let mut out = 0.0;
/// let mut dout = 0.0;
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
/// // (out, dout) == (400.0, -400.0)
/// }
/// ```
///
/// We might want to track how one input float affects one or more output floats. In this case,
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
/// more efficient if we have more output floats marked as `Dual` than input floats.
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand All@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
///
/// `Active` can be used for float scalar values.
/// If used on an input, a new float will be appended to the return tuple of the generated
/// function. If the function returns a float scalar, `Active` can be used for the return as
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
///
/// `Duplicated` can be used on references, raw pointers, or other indirect input
/// arguments. It creates a new shadow argument of the same type, following the original argument.
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
/// let mut output2 = 0.0;
/// let mut seed = 1.0;
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
/// }
/// ```
///
///
/// We often want to track how one or more input floats affect one output float. This output can
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
/// shadow of the outputs ("seed") will be reset to zero.
/// If the function has more than one output float marked as active or duplicated, users might want to
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a bit unclear to me how the 1.0 and 0.0 are used to specify the partial derivatives. I would assume the output given 1.0 has it's derivative evaluated and the one 0.0 not, but I think it would be good to be explicit in the docs.

/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
/// inputs.
/// Reverse mode is generally more efficient if we have more active/duplicated input than
/// output floats.
///
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand Down
1 change: 1 addition & 0 deletions library/std/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
# a borrow error occurs
debug_refcell = ["core/debug_refcell"]

llvm_enzyme = ["core/llvm_enzyme"]

# Enable std_detect features:
std_detect_file_io = ["std_detect/std_detect_file_io"]
Expand Down
1 change: 1 addition & 0 deletions library/sysroot/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
std_detect_file_io = ["std/std_detect_file_io"]
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
windows_raw_dylib = ["std/windows_raw_dylib"]
llvm_enzyme = ["std/llvm_enzyme"]
4 changes: 4 additions & 0 deletions src/bootstrap/src/lib.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -846,6 +846,10 @@ impl Build {
features.insert("compiler-builtins-mem");
}

if self.config.llvm_enzyme {
features.insert("llvm_enzyme");
}

features.into_iter().collect::<Vec<_>>().join(" ")
}

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions library/core/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@ optimize_for_size = []
# Make `RefCell` store additional debugging information, which is printed out when
# a borrow error occurs
debug_refcell = []
llvm_enzyme = []

[lints.rust.unexpected_cfgs]
level = "warn"
Expand All@@ -38,4 +39,6 @@ check-cfg = [
'cfg(target_has_reliable_f16_math)',
'cfg(target_has_reliable_f128)',
'cfg(target_has_reliable_f128_math)',
'cfg(llvm_enzyme)',

]
103 changes: 103 additions & 0 deletions library/core/src/macros/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
/// indirect input arguments. It can also be used on a scalar float return value.
/// If used on a return value, the generated function will return a tuple of two float scalars.
/// If used on an input argument, a new shadow argument of the same type will be created,
/// directly following the original argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
/// // When seeding both arguments at once the tangent return is the sum of both.
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
///
/// let mut out = 0.0;
/// let mut dout = 0.0;
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
/// // (out, dout) == (400.0, -400.0)
/// }
/// ```
///
/// We might want to track how one input float affects one or more output floats. In this case,
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
/// more efficient if we have more output floats marked as `Dual` than input floats.
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand All@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
///
/// `Active` can be used for float scalar values.
/// If used on an input, a new float will be appended to the return tuple of the generated
/// function. If the function returns a float scalar, `Active` can be used for the return as
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
///
/// `Duplicated` can be used on references, raw pointers, or other indirect input
/// arguments. It creates a new shadow argument of the same type, following the original argument.
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
/// let mut output2 = 0.0;
/// let mut seed = 1.0;
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
/// }
/// ```
///
///
/// We often want to track how one or more input floats affect one output float. This output can
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
/// shadow of the outputs ("seed") will be reset to zero.
/// If the function has more than one output float marked as active or duplicated, users might want to
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a bit unclear to me how the 1.0 and 0.0 are used to specify the partial derivatives. I would assume the output given 1.0 has it's derivative evaluated and the one 0.0 not, but I think it would be good to be explicit in the docs.

/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
/// inputs.
/// Reverse mode is generally more efficient if we have more active/duplicated input than
/// output floats.
///
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand Down
1 change: 1 addition & 0 deletions library/std/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
# a borrow error occurs
debug_refcell = ["core/debug_refcell"]

llvm_enzyme = ["core/llvm_enzyme"]

# Enable std_detect features:
std_detect_file_io = ["std_detect/std_detect_file_io"]
Expand Down
1 change: 1 addition & 0 deletions library/sysroot/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
std_detect_file_io = ["std/std_detect_file_io"]
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
windows_raw_dylib = ["std/windows_raw_dylib"]
llvm_enzyme = ["std/llvm_enzyme"]
4 changes: 4 additions & 0 deletions src/bootstrap/src/lib.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -846,6 +846,10 @@ impl Build {
features.insert("compiler-builtins-mem");
}

if self.config.llvm_enzyme {
features.insert("llvm_enzyme");
}

features.into_iter().collect::<Vec<_>>().join(" ")
}

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions library/core/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@ optimize_for_size = []
# Make `RefCell` store additional debugging information, which is printed out when
# a borrow error occurs
debug_refcell = []
llvm_enzyme = []

[lints.rust.unexpected_cfgs]
level = "warn"
Expand All@@ -38,4 +39,6 @@ check-cfg = [
'cfg(target_has_reliable_f16_math)',
'cfg(target_has_reliable_f128)',
'cfg(target_has_reliable_f128_math)',
'cfg(llvm_enzyme)',

]
103 changes: 103 additions & 0 deletions library/core/src/macros/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
/// indirect input arguments. It can also be used on a scalar float return value.
/// If used on a return value, the generated function will return a tuple of two float scalars.
/// If used on an input argument, a new shadow argument of the same type will be created,
/// directly following the original argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
/// // When seeding both arguments at once the tangent return is the sum of both.
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
///
/// let mut out = 0.0;
/// let mut dout = 0.0;
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
/// // (out, dout) == (400.0, -400.0)
/// }
/// ```
///
/// We might want to track how one input float affects one or more output floats. In this case,
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
/// more efficient if we have more output floats marked as `Dual` than input floats.
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand All@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
///
/// `Active` can be used for float scalar values.
/// If used on an input, a new float will be appended to the return tuple of the generated
/// function. If the function returns a float scalar, `Active` can be used for the return as
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
///
/// `Duplicated` can be used on references, raw pointers, or other indirect input
/// arguments. It creates a new shadow argument of the same type, following the original argument.
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
/// let mut output2 = 0.0;
/// let mut seed = 1.0;
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
/// }
/// ```
///
///
/// We often want to track how one or more input floats affect one output float. This output can
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
/// shadow of the outputs ("seed") will be reset to zero.
/// If the function has more than one output float marked as active or duplicated, users might want to
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a bit unclear to me how the 1.0 and 0.0 are used to specify the partial derivatives. I would assume the output given 1.0 has it's derivative evaluated and the one 0.0 not, but I think it would be good to be explicit in the docs.

/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
/// inputs.
/// Reverse mode is generally more efficient if we have more active/duplicated input than
/// output floats.
///
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand Down
1 change: 1 addition & 0 deletions library/std/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
# a borrow error occurs
debug_refcell = ["core/debug_refcell"]

llvm_enzyme = ["core/llvm_enzyme"]

# Enable std_detect features:
std_detect_file_io = ["std_detect/std_detect_file_io"]
Expand Down
1 change: 1 addition & 0 deletions library/sysroot/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
std_detect_file_io = ["std/std_detect_file_io"]
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
windows_raw_dylib = ["std/windows_raw_dylib"]
llvm_enzyme = ["std/llvm_enzyme"]
4 changes: 4 additions & 0 deletions src/bootstrap/src/lib.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -846,6 +846,10 @@ impl Build {
features.insert("compiler-builtins-mem");
}

if self.config.llvm_enzyme {
features.insert("llvm_enzyme");
}

features.into_iter().collect::<Vec<_>>().join(" ")
}

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions library/core/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@ optimize_for_size = []
# Make `RefCell` store additional debugging information, which is printed out when
# a borrow error occurs
debug_refcell = []
llvm_enzyme = []

[lints.rust.unexpected_cfgs]
level = "warn"
Expand All@@ -38,4 +39,6 @@ check-cfg = [
'cfg(target_has_reliable_f16_math)',
'cfg(target_has_reliable_f128)',
'cfg(target_has_reliable_f128_math)',
'cfg(llvm_enzyme)',

]
103 changes: 103 additions & 0 deletions library/core/src/macros/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
/// indirect input arguments. It can also be used on a scalar float return value.
/// If used on a return value, the generated function will return a tuple of two float scalars.
/// If used on an input argument, a new shadow argument of the same type will be created,
/// directly following the original argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
/// // When seeding both arguments at once the tangent return is the sum of both.
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
///
/// let mut out = 0.0;
/// let mut dout = 0.0;
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
/// // (out, dout) == (400.0, -400.0)
/// }
/// ```
///
/// We might want to track how one input float affects one or more output floats. In this case,
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
/// more efficient if we have more output floats marked as `Dual` than input floats.
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand All@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
///
/// `Active` can be used for float scalar values.
/// If used on an input, a new float will be appended to the return tuple of the generated
/// function. If the function returns a float scalar, `Active` can be used for the return as
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
///
/// `Duplicated` can be used on references, raw pointers, or other indirect input
/// arguments. It creates a new shadow argument of the same type, following the original argument.
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
/// let mut output2 = 0.0;
/// let mut seed = 1.0;
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
/// }
/// ```
///
///
/// We often want to track how one or more input floats affect one output float. This output can
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
/// shadow of the outputs ("seed") will be reset to zero.
/// If the function has more than one output float marked as active or duplicated, users might want to
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a bit unclear to me how the 1.0 and 0.0 are used to specify the partial derivatives. I would assume the output given 1.0 has it's derivative evaluated and the one 0.0 not, but I think it would be good to be explicit in the docs.

/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
/// inputs.
/// Reverse mode is generally more efficient if we have more active/duplicated input than
/// output floats.
///
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand Down
1 change: 1 addition & 0 deletions library/std/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
# a borrow error occurs
debug_refcell = ["core/debug_refcell"]

llvm_enzyme = ["core/llvm_enzyme"]

# Enable std_detect features:
std_detect_file_io = ["std_detect/std_detect_file_io"]
Expand Down
1 change: 1 addition & 0 deletions library/sysroot/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
std_detect_file_io = ["std/std_detect_file_io"]
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
windows_raw_dylib = ["std/windows_raw_dylib"]
llvm_enzyme = ["std/llvm_enzyme"]
4 changes: 4 additions & 0 deletions src/bootstrap/src/lib.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -846,6 +846,10 @@ impl Build {
features.insert("compiler-builtins-mem");
}

if self.config.llvm_enzyme {
features.insert("llvm_enzyme");
}

features.into_iter().collect::<Vec<_>>().join(" ")
}

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions library/core/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@ optimize_for_size = []
# Make `RefCell` store additional debugging information, which is printed out when
# a borrow error occurs
debug_refcell = []
llvm_enzyme = []

[lints.rust.unexpected_cfgs]
level = "warn"
Expand All@@ -38,4 +39,6 @@ check-cfg = [
'cfg(target_has_reliable_f16_math)',
'cfg(target_has_reliable_f128)',
'cfg(target_has_reliable_f128_math)',
'cfg(llvm_enzyme)',

]
103 changes: 103 additions & 0 deletions library/core/src/macros/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
/// indirect input arguments. It can also be used on a scalar float return value.
/// If used on a return value, the generated function will return a tuple of two float scalars.
/// If used on an input argument, a new shadow argument of the same type will be created,
/// directly following the original argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
/// // When seeding both arguments at once the tangent return is the sum of both.
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
///
/// let mut out = 0.0;
/// let mut dout = 0.0;
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
/// // (out, dout) == (400.0, -400.0)
/// }
/// ```
///
/// We might want to track how one input float affects one or more output floats. In this case,
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
/// more efficient if we have more output floats marked as `Dual` than input floats.
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand All@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
///
/// `Active` can be used for float scalar values.
/// If used on an input, a new float will be appended to the return tuple of the generated
/// function. If the function returns a float scalar, `Active` can be used for the return as
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
///
/// `Duplicated` can be used on references, raw pointers, or other indirect input
/// arguments. It creates a new shadow argument of the same type, following the original argument.
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
/// let mut output2 = 0.0;
/// let mut seed = 1.0;
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
/// }
/// ```
///
///
/// We often want to track how one or more input floats affect one output float. This output can
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
/// shadow of the outputs ("seed") will be reset to zero.
/// If the function has more than one output float marked as active or duplicated, users might want to
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a bit unclear to me how the 1.0 and 0.0 are used to specify the partial derivatives. I would assume the output given 1.0 has it's derivative evaluated and the one 0.0 not, but I think it would be good to be explicit in the docs.

/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
/// inputs.
/// Reverse mode is generally more efficient if we have more active/duplicated input than
/// output floats.
///
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand Down
1 change: 1 addition & 0 deletions library/std/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
# a borrow error occurs
debug_refcell = ["core/debug_refcell"]

llvm_enzyme = ["core/llvm_enzyme"]

# Enable std_detect features:
std_detect_file_io = ["std_detect/std_detect_file_io"]
Expand Down
1 change: 1 addition & 0 deletions library/sysroot/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
std_detect_file_io = ["std/std_detect_file_io"]
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
windows_raw_dylib = ["std/windows_raw_dylib"]
llvm_enzyme = ["std/llvm_enzyme"]
4 changes: 4 additions & 0 deletions src/bootstrap/src/lib.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -846,6 +846,10 @@ impl Build {
features.insert("compiler-builtins-mem");
}

if self.config.llvm_enzyme {
features.insert("llvm_enzyme");
}

features.into_iter().collect::<Vec<_>>().join(" ")
}

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions library/core/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@ optimize_for_size = []
# Make `RefCell` store additional debugging information, which is printed out when
# a borrow error occurs
debug_refcell = []
llvm_enzyme = []

[lints.rust.unexpected_cfgs]
level = "warn"
Expand All@@ -38,4 +39,6 @@ check-cfg = [
'cfg(target_has_reliable_f16_math)',
'cfg(target_has_reliable_f128)',
'cfg(target_has_reliable_f128_math)',
'cfg(llvm_enzyme)',

]
103 changes: 103 additions & 0 deletions library/core/src/macros/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
/// indirect input arguments. It can also be used on a scalar float return value.
/// If used on a return value, the generated function will return a tuple of two float scalars.
/// If used on an input argument, a new shadow argument of the same type will be created,
/// directly following the original argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
/// // When seeding both arguments at once the tangent return is the sum of both.
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
///
/// let mut out = 0.0;
/// let mut dout = 0.0;
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
/// // (out, dout) == (400.0, -400.0)
/// }
/// ```
///
/// We might want to track how one input float affects one or more output floats. In this case,
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
/// more efficient if we have more output floats marked as `Dual` than input floats.
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand All@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
///
/// `Active` can be used for float scalar values.
/// If used on an input, a new float will be appended to the return tuple of the generated
/// function. If the function returns a float scalar, `Active` can be used for the return as
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
///
/// `Duplicated` can be used on references, raw pointers, or other indirect input
/// arguments. It creates a new shadow argument of the same type, following the original argument.
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
/// let mut output2 = 0.0;
/// let mut seed = 1.0;
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
/// }
/// ```
///
///
/// We often want to track how one or more input floats affect one output float. This output can
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
/// shadow of the outputs ("seed") will be reset to zero.
/// If the function has more than one output float marked as active or duplicated, users might want to
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a bit unclear to me how the 1.0 and 0.0 are used to specify the partial derivatives. I would assume the output given 1.0 has it's derivative evaluated and the one 0.0 not, but I think it would be good to be explicit in the docs.

/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
/// inputs.
/// Reverse mode is generally more efficient if we have more active/duplicated input than
/// output floats.
///
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand Down
1 change: 1 addition & 0 deletions library/std/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
# a borrow error occurs
debug_refcell = ["core/debug_refcell"]

llvm_enzyme = ["core/llvm_enzyme"]

# Enable std_detect features:
std_detect_file_io = ["std_detect/std_detect_file_io"]
Expand Down
1 change: 1 addition & 0 deletions library/sysroot/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
std_detect_file_io = ["std/std_detect_file_io"]
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
windows_raw_dylib = ["std/windows_raw_dylib"]
llvm_enzyme = ["std/llvm_enzyme"]
4 changes: 4 additions & 0 deletions src/bootstrap/src/lib.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -846,6 +846,10 @@ impl Build {
features.insert("compiler-builtins-mem");
}

if self.config.llvm_enzyme {
features.insert("llvm_enzyme");
}

features.into_iter().collect::<Vec<_>>().join(" ")
}

Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions library/core/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@ optimize_for_size = []
# Make `RefCell` store additional debugging information, which is printed out when
# a borrow error occurs
debug_refcell = []
llvm_enzyme = []

[lints.rust.unexpected_cfgs]
level = "warn"
Expand All@@ -38,4 +39,6 @@ check-cfg = [
'cfg(target_has_reliable_f16_math)',
'cfg(target_has_reliable_f128)',
'cfg(target_has_reliable_f128_math)',
'cfg(llvm_enzyme)',

]
103 changes: 103 additions & 0 deletions library/core/src/macros/mod.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -1499,6 +1499,55 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Dual` or `Const`, more options will be exposed later.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// `Dual` can be used for float scalar values or for references, raw pointers, or other
/// indirect input arguments. It can also be used on a scalar float return value.
/// If used on a return value, the generated function will return a tuple of two float scalars.
/// If used on an input argument, a new shadow argument of the same type will be created,
/// directly following the original argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_forward(rb_fwd1, Dual, Const, Dual)]
/// #[autodiff_forward(rb_fwd2, Const, Dual, Dual)]
/// #[autodiff_forward(rb_fwd3, Dual, Dual, Dual)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_forward(rb_inp_fwd, Dual, Dual, Dual)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let x0 = rosenbrock(1.0, 3.0); // 400.0
/// let (x1, dx1) = rb_fwd1(1.0, 1.0, 3.0); // (400.0, -800.0)
/// let (x2, dy1) = rb_fwd2(1.0, 3.0, 1.0); // (400.0, 400.0)
/// // When seeding both arguments at once the tangent return is the sum of both.
/// let (x3, dxy) = rb_fwd3(1.0, 1.0, 3.0, 1.0); // (400.0, -400.0)
///
/// let mut out = 0.0;
/// let mut dout = 0.0;
/// rb_inp_fwd(1.0, 1.0, 3.0, 1.0, &mut out, &mut dout);
/// // (out, dout) == (400.0, -400.0)
/// }
/// ```
///
/// We might want to track how one input float affects one or more output floats. In this case,
/// the shadow of one input should be initialized to `1.0`, while the shadows of the other
/// inputs should be initialized to `0.0`. The shadow of the output(s) should be initialized to
/// `0.0`. After calling the generated function, the shadow of the input will be zeroed,
/// while the shadow(s) of the output(s) will contain the derivatives. Forward mode is generally
/// more efficient if we have more output floats marked as `Dual` than input floats.
/// Related information can also be found under the term "Vector-Jacobian product" (VJP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand All@@ -1518,6 +1567,60 @@ pub(crate) mod builtin {
/// - `INPUT_ACTIVITIES`: Specifies one valid activity for each input parameter.
/// - `OUTPUT_ACTIVITY`: Must not be set if the function implicitly returns nothing
/// (or explicitly returns `-> ()`). Otherwise, it must be set to one of the allowed activities.
///
/// ACTIVITIES might either be `Active`, `Duplicated` or `Const`, more options will be exposed later.
///
/// `Active` can be used for float scalar values.
/// If used on an input, a new float will be appended to the return tuple of the generated
/// function. If the function returns a float scalar, `Active` can be used for the return as
/// well. In this case a float scalar will be appended to the argument list, it works as seed.
///
/// `Duplicated` can be used on references, raw pointers, or other indirect input
/// arguments. It creates a new shadow argument of the same type, following the original argument.
/// A const reference or pointer argument will receive a mutable reference or pointer as shadow.
///
/// `Const` should be used on non-float arguments, or float-based arguments as an optimization
/// if we are not interested in computing the derivatives with respect to this argument.
///
/// ### Usage examples:
///
/// ```rust,ignore (autodiff requires a -Z flag as well as fat-lto for testing)
/// #![feature(autodiff)]
/// use std::autodiff::*;
/// #[autodiff_reverse(rb_rev, Active, Active, Active)]
/// fn rosenbrock(x: f64, y: f64) -> f64 {
/// (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2)
/// }
/// #[autodiff_reverse(rb_inp_rev, Active, Active, Duplicated)]
/// fn rosenbrock_inp(x: f64, y: f64, out: &mut f64) {
/// *out = (1.0 - x).powi(2) + 100.0 * (y - x.powi(2)).powi(2);
/// }
///
/// fn main() {
/// let (output1, dx1, dy1) = rb_rev(1.0, 3.0, 1.0);
/// dbg!(output1, dx1, dy1); // (400.0, -800.0, 400.0)
/// let mut output2 = 0.0;
/// let mut seed = 1.0;
/// let (dx2, dy2) = rb_inp_rev(1.0, 3.0, &mut output2, &mut seed);
/// // (dx2, dy2, output2, seed) == (-800.0, 400.0, 400.0, 0.0)
/// }
/// ```
///
///
/// We often want to track how one or more input floats affect one output float. This output can
/// be a scalar return value, or a mutable reference or pointer argument. In the latter case, the
/// mutable input should be marked as duplicated and its shadow initialized to `0.0`. The shadow of
/// the output should be marked as active or duplicated and initialized to `1.0`. After calling
/// the generated function, the shadow(s) of the input(s) will contain the derivatives. The
/// shadow of the outputs ("seed") will be reset to zero.
/// If the function has more than one output float marked as active or duplicated, users might want to
/// set one of them to `1.0` and the others to `0.0` to compute partial derivatives.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a bit unclear to me how the 1.0 and 0.0 are used to specify the partial derivatives. I would assume the output given 1.0 has it's derivative evaluated and the one 0.0 not, but I think it would be good to be explicit in the docs.

/// Unlike forward-mode, a call to the generated function does not reset the shadow of the
/// inputs.
/// Reverse mode is generally more efficient if we have more active/duplicated input than
/// output floats.
///
/// Related information can also be found under the term "Jacobian-Vector Product" (JVP).
#[unstable(feature = "autodiff", issue = "124509")]
#[allow_internal_unstable(rustc_attrs)]
#[allow_internal_unstable(core_intrinsics)]
Expand Down
1 change: 1 addition & 0 deletions library/std/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -126,6 +126,7 @@ optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
# a borrow error occurs
debug_refcell = ["core/debug_refcell"]

llvm_enzyme = ["core/llvm_enzyme"]

# Enable std_detect features:
std_detect_file_io = ["std_detect/std_detect_file_io"]
Expand Down
1 change: 1 addition & 0 deletions library/sysroot/Cargo.toml
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,3 +35,4 @@ profiler = ["dep:profiler_builtins"]
std_detect_file_io = ["std/std_detect_file_io"]
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
windows_raw_dylib = ["std/windows_raw_dylib"]
llvm_enzyme = ["std/llvm_enzyme"]
4 changes: 4 additions & 0 deletions src/bootstrap/src/lib.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -846,6 +846,10 @@ impl Build {
features.insert("compiler-builtins-mem");
}

if self.config.llvm_enzyme {
features.insert("llvm_enzyme");
}

features.into_iter().collect::<Vec<_>>().join(" ")
}

Expand Down
Loading