// Copyright 2025 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
/// Normalizes an angle to the range \[0, 2PI) radians.
///
/// Parameters:
///
/// * `angle` : The angle in radians to normalize.
///
/// Returns the normalized angle in the range \[0, 2PI) radians.
///
/// Example:
///
/// ```moonbit nocheck
/// // Positive angle greater than 2PI
/// inspect(@cmath.normalize_angle(7.0), content="0.7168146928204138")
///
/// // Negative angle
/// inspect(@cmath.normalize_angle(-1.0), content="5.283185307179586")
///
/// // Angle already in range
/// inspect(@cmath.normalize_angle(1.5), content="1.5")
/// ```
///
pub fn normalize_angle(angle : Double) -> Double {
let two_pi = @cmath.PI * 2
let angle = angle % two_pi
if angle < 0.0 {
angle + two_pi
} else {
angle
}
}
///|
test "normalize_angle" {
// Test positive angles greater than 2π
inspect(normalize_angle(7.0), content="0.7168146928204138")
// Test negative angles
inspect(normalize_angle(-1.0), content="5.283185307179586")
// Test angles already in range [0, 2π)
inspect(normalize_angle(1.5), content="1.5")
inspect(normalize_angle(0.0), content="0")
// Test angle exactly at 2π (should normalize to 0)
inspect(normalize_angle(@cmath.PI * 2.0), content="0")
}
///|
test "normalize_angle/edge_cases" {
// Test very large positive angles
inspect(normalize_angle(100.0), content="5.7522203923062065")
// Test very large negative angles
inspect(normalize_angle(-100.0), content="0.5309649148733797")
// Test multiple full rotations
inspect(normalize_angle(@cmath.PI * 6.0), content="0")
inspect(normalize_angle(@cmath.PI * -4.0), content="0")
}
///|
test "normalize_angle/boundary_values" {
// Test just under 2π
let almost_two_pi = @cmath.PI * 2.0 - 0.001
inspect(normalize_angle(almost_two_pi), content="6.282185307179586")
// Test just over 0 when coming from negative
let small_negative = -0.001
inspect(normalize_angle(small_negative), content="6.282185307179586")
}