@@ -809,6 +809,52 @@ static sd::Tensor<float> sample_euler_ancestral(denoise_cb_t model,
809809 return x;
810810}
811811
812+ static sd::Tensor<float > sample_euler_flow (denoise_cb_t model,
813+ sd::Tensor<float > x,
814+ const std::vector<float >& sigmas,
815+ std::shared_ptr<RNG> rng,
816+ float eta) {
817+ int steps = static_cast <int >(sigmas.size ()) - 1 ;
818+ for (int i = 0 ; i < steps; i++) {
819+ float sigma = sigmas[i];
820+ float sigma_to = sigmas[i + 1 ];
821+ auto denoised_opt = model (x, sigma, i + 1 );
822+ if (denoised_opt.empty ()) {
823+ return {};
824+ }
825+ sd::Tensor<float > denoised = std::move (denoised_opt);
826+ if (sigma_to == 0 ) {
827+ // x = x × (sigma_to / sigma) + denoised × (1 - (sigma_to / sigma)) // below
828+ // = x × ( 0 / sigma) + denoised × (1 - (0 / sigma))
829+ // = denoised
830+ x = denoised;
831+ } else if (eta == 0 ) {
832+ // x = x + d × (sigma_to - sigma)
833+ // = x + ((x - denoised) / sigma) × (sigma_to - sigma)
834+ // = x + (x - denoised) × (sigma_to / sigma - 1)
835+ // = x + x × (sigma_to / sigma) - x - denoised × (sigma_to / sigma) + denoised
836+ // = x × (sigma_to / sigma) + denoised × (1 - (sigma_to / sigma))
837+ float sigma_ratio = sigma_to / sigma;
838+ x = sigma_ratio * x + (1.0 - sigma_ratio) * denoised;
839+ } else {
840+ float downstep_ratio = 1 .0f + (sigma_to / sigma - 1 .0f ) * eta;
841+ float sigma_down = sigma_to * downstep_ratio;
842+ float sigma_ratio = sigma_down / sigma;
843+ x = sigma_ratio * x + (1.0 - sigma_ratio) * denoised;
844+
845+ float alpha_scale = (1 - sigma_to) / (1 - sigma_down);
846+
847+ // sigma_up = √(sigma_to² - sigma_down² × alpha_scale²)
848+ // = √(sigma_to² - sigma_to² × downstep_ratio² × alpha_scale²)
849+ // = sigma_to × √(1 - downstep_ratio² × alpha_scale²)
850+ float term = downstep_ratio * alpha_scale;
851+ float sigma_up = sigma_to * std::sqrt ((1 .0f + term) * (1 .0f - term));
852+ x = alpha_scale * x + sd::Tensor<float >::randn_like (x, rng) * sigma_up;
853+ }
854+ }
855+ return x;
856+ }
857+
812858static sd::Tensor<float > sample_euler (denoise_cb_t model,
813859 sd::Tensor<float > x,
814860 const std::vector<float >& sigmas) {
@@ -1370,10 +1416,14 @@ static sd::Tensor<float> sample_k_diffusion(sample_method_t method,
13701416 sd::Tensor<float > x,
13711417 std::vector<float > sigmas,
13721418 std::shared_ptr<RNG> rng,
1373- float eta) {
1419+ float eta,
1420+ bool is_flow_denoiser) {
13741421 switch (method) {
13751422 case EULER_A_SAMPLE_METHOD:
1376- return sample_euler_ancestral (model, std::move (x), sigmas, rng, eta);
1423+ if (is_flow_denoiser)
1424+ return sample_euler_flow (model, std::move (x), sigmas, rng, eta);
1425+ else
1426+ return sample_euler_ancestral (model, std::move (x), sigmas, rng, eta);
13771427 case EULER_SAMPLE_METHOD:
13781428 return sample_euler (model, std::move (x), sigmas);
13791429 case HEUN_SAMPLE_METHOD:
0 commit comments