1/*
2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16export class MathCordic  {
17    static readonly AG_CONST : double = 0.6072529350;
18    static readonly TARGET_ANGLE : double = 28.027;
19    static readonly expected : double = 10362.570468755888;
20    static readonly ANGLES : double[] = [MathCordic.fnFixed(45.0), MathCordic.fnFixed(26.565), MathCordic.fnFixed(14.0362), MathCordic.fnFixed(7.12502), MathCordic.fnFixed(3.57633), MathCordic.fnFixed(1.78991), MathCordic.fnFixed(0.895174), MathCordic.fnFixed(0.447614), MathCordic.fnFixed(0.223811), MathCordic.fnFixed(0.111906), MathCordic.fnFixed(0.055953), MathCordic.fnFixed(0.027977)];
21
22    static fnFixed(x : double): double {
23        return x * 65536.0;
24    }
25
26    static fnFloat(x : double): double {
27        return x / 65536.0;
28    }
29
30    static fnDegToRad(x : double): double {
31        return 0.017453 * x;
32    }
33
34    static cordicsincos(target : double): double {
35        let x : double;
36        let y : double;
37        let targetAngle : double = MathCordic.fnFixed(target);
38        let currAngle : double = 0;
39        let step : int ;
40        x = MathCordic.fnFixed(MathCordic.AG_CONST * cos(0));
41        y = sin(0);
42        for (step = 0; step < 12; step++) {
43            let newX : double ;
44            if (targetAngle > currAngle) {
45                newX = x - (y as int >> step);
46                y = (x as int >> step) + y;
47                x = newX;
48                currAngle += MathCordic.ANGLES[step];
49            }
50            else {
51                newX = x + (y as int >> step);
52                y = -(x as int >> step) + y;
53                x = newX;
54                currAngle -= MathCordic.ANGLES[step];
55            }
56        }
57        return MathCordic.fnFloat(x) * MathCordic.fnFloat(y);
58    }
59
60    static cordic(runs : int): double {
61        let total : double = 0;
62        for (let i : int = 0; i < runs; i++) {
63            total += MathCordic.cordicsincos(MathCordic.TARGET_ANGLE);
64        }
65        return total;
66    }
67
68    n : int;
69
70    public run(): void {
71        this.n = 25000;
72        let total : double = MathCordic.cordic(this.n);
73
74        assert total == MathCordic.expected: "Incorrect result";
75    }
76}
77
78function main(): void {
79  let a = new MathCordic;
80  a.run();
81}
82
83