// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using AutomatedUITests;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium.Appium.Windows;
using WindowsTestHelpers;

namespace AutomatedUITests.Tests
{
    [TestClass]
    public class LaunchBothAppsAndCompareAllMenuBarPages
    {
        private string AppFileNameFormat { get; } = "CompareMenuBarPages-{0}-{1}.png";

        [TestMethod]
        public void CompareScreenshotsOfAllPages()
        {
            WinAppDriverHelper.StartIfNotRunning();

            if (!Directory.Exists(TestAppInfo.ScreenshotsFolder))
            {
                Directory.CreateDirectory(TestAppInfo.ScreenshotsFolder);
            }

            // Hide other apps to all a consistent backdrop for acrylic textures
            VirtualKeyboard.MinimizeAllWindows();

            using (var appSession1 = WinAppDriverHelper.LaunchAppx(TestAppInfo.AppPfn1))
            {
                appSession1.Manage().Window.Maximize();

                Task.Delay(TimeSpan.FromSeconds(2)).Wait();

                var menuItems = appSession1.FindElementsByClassName("Microsoft.UI.Xaml.Controls.MenuBarItem");

                menuItems[1].Click(); // Open menu to count sub-items
                var subItemCount = appSession1.FindElementsByClassName("MenuFlyoutItem").Count;
                menuItems[1].Click(); // Close menu so get in a consistent state

                // Stepping through the MenuFlyoutItems is unreliable
                for (int j = 0; j < subItemCount; j++)
                {
                    menuItems[1].Click(); // Open the menu again

                    var subItems = appSession1.FindElementsByClassName("MenuFlyoutItem");
                    subItems[j].Click();
                    Task.Delay(TimeSpan.FromMilliseconds(1500)).Wait(); // Allow page to load and animations to complete

                    var screenshot = appSession1.GetScreenshot();
                    var fileName = string.Format(AppFileNameFormat, TestAppInfo.AppName1, subItems[j].Text);
                    screenshot.SaveAsFile(Path.Combine(TestAppInfo.ScreenshotsFolder, fileName), ImageFormat.Png);
                }

                // Don't leave the app maximized in case we want to open the app again.
                // Some controls handle layout differently when the app is first opened maximized
                VirtualKeyboard.RestoreMaximizedWindow();
            }

            using (var appSession2 = WinAppDriverHelper.LaunchAppx(TestAppInfo.AppPfn2))
            {
                appSession2.Manage().Window.Maximize();

                Task.Delay(TimeSpan.FromSeconds(2)).Wait();

                var menuItems = appSession2.FindElementsByClassName("Microsoft.UI.Xaml.Controls.MenuBarItem");

                menuItems[1].Click(); // Open menu to count sub-items
                var subItemCount = appSession2.FindElementsByClassName("MenuFlyoutItem").Count;
                menuItems[1].Click(); // Close menu so get in a consistent state

                // Stepping through the MenuFlyoutItems is unreliable
                for (int j = 0; j < subItemCount; j++)
                {
                    menuItems[1].Click(); // Open the menu again

                    var subItems = appSession2.FindElementsByClassName("MenuFlyoutItem");
                    subItems[j].Click();
                    Task.Delay(TimeSpan.FromMilliseconds(1500)).Wait(); // Allow page to load and animations to complete

                    var screenshot = appSession2.GetScreenshot();
                    var fileName = string.Format(AppFileNameFormat, TestAppInfo.AppName2, subItems[j].Text);
                    screenshot.SaveAsFile(Path.Combine(TestAppInfo.ScreenshotsFolder, fileName), ImageFormat.Png);
                }

                // Don't leave the app maximized in case we want to open the app again.
                // Some controls handle layout differently when the app is first opened maximized
                VirtualKeyboard.RestoreMaximizedWindow();
            }

            var app1Images = Directory.GetFiles(TestAppInfo.ScreenshotsFolder, $"*-{TestAppInfo.AppName1}*.png");

            var allImagesCount = Directory.GetFiles(TestAppInfo.ScreenshotsFolder, "*.png").Length;

            if (allImagesCount != app1Images.Length * 2)
            {
                Assert.Fail($"Did not produce equal number of page screenshots for each app. {TestAppInfo.ScreenshotsFolder}");
            }

            var nonMatchingImages = new List<string>();

            var toDelete = new List<string>();

            foreach (var file in app1Images)
            {
                var equivFile = file.Replace(TestAppInfo.AppName1, TestAppInfo.AppName2);

                var imagesAreTheSame = CheckImagesAreTheSame(TestAppInfo.ScreenshotsFolder, file, equivFile);

                if (imagesAreTheSame)
                {
                    toDelete.Add(file);
                    toDelete.Add(equivFile);
                }
                else
                {
                    nonMatchingImages.Add(equivFile);
                }
            }

            foreach (var fileToDelete in toDelete)
            {
                Task.Run(() =>
                {
                    try
                    {
                        File.Delete(fileToDelete);
                    }
                    catch (Exception)
                    {
                        Task.Delay(TimeSpan.FromSeconds(5)).Wait();
                        File.Delete(fileToDelete);
                    }
                });

            }

            Assert.IsFalse(nonMatchingImages.Any(), string.Join(Environment.NewLine, nonMatchingImages));
        }

        private bool CheckImagesAreTheSame(string folder, string fileName1, string fileName2)
        {
            var imagePath1 = Path.Combine(folder, fileName1);
            var imagePath2 = Path.Combine(folder, fileName2);

            var image1 = Image.FromFile(imagePath1);
            var image2 = Image.FromFile(imagePath2);

            var pageName = Path.GetFileNameWithoutExtension(imagePath1).Split('-').Last();
            var exclusionAreas = GetAllExclusionAreas(pageName);
            var percentageDifference = ImageComparer.PercentageDifferent(image1, image2, exclusionAreas);

            if (percentageDifference > 0f)
            {
                var diffImage = image1.GetDifferenceImage(image2, exclusionAreas);

                diffImage.Save(Path.Combine(folder, $"DIFF-{Path.GetFileName(fileName2)}"), ImageFormat.Png);

                return false;
            }
            else
            {
                return true;
            }
        }

        private ImageComparer.ExclusionArea[] GetAllExclusionAreas(string pageSpecific = null)
        {
            var hasPageSpecific = !string.IsNullOrWhiteSpace(pageSpecific) && TestAppInfo.PageSpecificExclusions.ContainsKey(pageSpecific);
            // Extra on all pages + app bar title + page specific
            var finalCount = TestAppInfo.ExclusionAreas.Length + 1 + (hasPageSpecific ? 1 : 0);

            var result = new ImageComparer.ExclusionArea[finalCount];

            // We always exclude the area the app name occupies in the title bar as these will always be different
            result[0] = new ImageComparer.ExclusionArea(new Rectangle(0, 0, 600, 40), scaleFactor: 1.25f);

            Array.Copy(TestAppInfo.ExclusionAreas, 0, result, 1, TestAppInfo.ExclusionAreas.Length);

            if (hasPageSpecific)
            {
                result[finalCount - 1] = TestAppInfo.PageSpecificExclusions[pageSpecific];
            }

            return result;
        }
    }
}


describe('Array', function() {
    var testSubject;
    beforeEach(function() {
        testSubject = [2, 3, undefined, true, 'hej', null, false, 0];
        delete testSubject[1];
    });
    function createArrayLikeFromArray(arr) {
        var o = {};
        Array.prototype.forEach.call(arr, function(e, i) {
            o[i]=e;
        });
        o.length = arr.length;
        return o;
    };

    describe('forEach', function() {
        "use strict";
        var expected, actual;

        beforeEach(function() {
            expected = {0:2, 2: undefined, 3:true, 4: 'hej', 5:null, 6:false, 7:0 };
            actual = {};
        });
        it('should pass the right parameters', function() {
            var callback = jasmine.createSpy('callback'),
                array = ['1'];
            array.forEach(callback);
            expect(callback).toHaveBeenCalledWith('1', 0, array);
        });
        it('should not affect elements added to the array after it has begun', function() {
            var arr = [1,2,3],
                i = 0;
            arr.forEach(function(a) {
                i++;
                arr.push(a+3);
            });
            expect(arr).toEqual([1,2,3,4,5,6]);
            expect(i).toBe(3);
        });

        it('should set the right context when given none', function() {
            var context;
            [1].forEach(function() {context = this;});
            expect(context).toBe(function() {return this}.call());
        });
        it('should iterate all', function() {
            testSubject.forEach(function(obj, index) {
                actual[index] = obj;
            });
            expect(actual).toExactlyMatch(expected);
        });
        it('should iterate all using a context', function() {
            var o = { a: actual };

            testSubject.forEach(function(obj, index) {
                this.a[index] = obj;
            }, o);
            expect(actual).toExactlyMatch(expected);
        });

        it('should iterate all in an array-like object', function() {
            var ts = createArrayLikeFromArray(testSubject);
            Array.prototype.forEach.call(ts, function(obj, index) {
                actual[index] = obj;
            });
            expect(actual).toExactlyMatch(expected);
        });
        it('should iterate all in an array-like object using a context', function() {
            var ts = createArrayLikeFromArray(testSubject),
                o = { a: actual };

            Array.prototype.forEach.call(ts, function(obj, index) {
                this.a[index] = obj;
            }, o);
            expect(actual).toExactlyMatch(expected);
        });
    });
    describe('some', function() {
        var actual, expected, numberOfRuns;

        beforeEach(function() {
            expected = {0:2, 2: undefined, 3:true };
            actual = {};
            numberOfRuns = 0;
        });

        it('should pass the correct values along to the callback', function() {
            var callback = jasmine.createSpy('callback');
            var array = ['1'];
            array.some(callback);
            expect(callback).toHaveBeenCalledWith('1', 0, array);
        });
        it('should not affect elements added to the array after it has begun', function() {
            var arr = [1,2,3],
                i = 0;
            arr.some(function(a) {
                i++;
                arr.push(a+3);
                return i > 3;
            });
            expect(arr).toEqual([1,2,3,4,5,6]);
            expect(i).toBe(3);
        });
        it('should set the right context when given none', function() {
            var context;
            [1].some(function() {context = this;});
            expect(context).toBe(function() {return this}.call());
        });

        it('should return false if it runs to the end', function() {
            actual = testSubject.some(function() {});
            expect(actual).toBeFalsy();
        });
        it('should return true if it is stopped somewhere', function() {
            actual = testSubject.some(function() { return true; });
            expect(actual).toBeTruthy();
        });
        it('should return false if there are no elements', function() {
            actual = [].some(function() { return true; });
            expect(actual).toBeFalsy();
        });

        it('should stop after 3 elements', function() {
            testSubject.some(function(obj, index) {
                actual[index] = obj;
                numberOfRuns += 1;
                if(numberOfRuns == 3) {
                    return true;
                }
                return false;
            });
            expect(actual).toExactlyMatch(expected);
        });
        it('should stop after 3 elements using a context', function() {
            var o = { a: actual };
            testSubject.some(function(obj, index) {
                this.a[index] = obj;
                numberOfRuns += 1;
                if(numberOfRuns == 3) {
                    return true;
                }
                return false;
            }, o);
            expect(actual).toExactlyMatch(expected);
        });

        it('should stop after 3 elements in an array-like object', function() {
            var ts = createArrayLikeFromArray(testSubject);
            Array.prototype.some.call(ts, function(obj, index) {
                actual[index] = obj;
                numberOfRuns += 1;
                if(numberOfRuns == 3) {
                    return true;
                }
                return false;
            });
            expect(actual).toExactlyMatch(expected);
        });
        it('should stop after 3 elements in an array-like object using a context', function() {
            var ts = createArrayLikeFromArray(testSubject);
            var o = { a: actual };
            Array.prototype.some.call(ts, function(obj, index) {
                this.a[index] = obj;
                numberOfRuns += 1;
                if(numberOfRuns == 3) {
                    return true;
                }
                return false;
            }, o);
            expect(actual).toExactlyMatch(expected);
        });
    });
    describe('every', function() {
        var actual, expected, numberOfRuns;

        beforeEach(function() {
            expected = {0:2, 2: undefined, 3:true };
            actual = {};
            numberOfRuns = 0;
        });

        it('should pass the correct values along to the callback', function() {
            var callback = jasmine.createSpy('callback');
            var array = ['1'];
            array.every(callback);
            expect(callback).toHaveBeenCalledWith('1', 0, array);
        });
        it('should not affect elements added to the array after it has begun', function() {
            var arr = [1,2,3],
                i = 0;
            arr.every(function(a) {
                i++;
                arr.push(a+3);
                return i <= 3;
            });
            expect(arr).toEqual([1,2,3,4,5,6]);
            expect(i).toBe(3);
        });
        it('should set the right context when given none', function() {
            var context;
            [1].every(function() {context = this;});
            expect(context).toBe(function() {return this}.call());
        });

        it('should return true if the array is empty', function() {
            actual = [].every(function() { return true; });
            expect(actual).toBeTruthy();

            actual = [].every(function() { return false; });
            expect(actual).toBeTruthy();
        });
        it('should return true if it runs to the end', function() {
            actual = [1,2,3].every(function() { return true; });
            expect(actual).toBeTruthy();
        });
        it('should return false if it is stopped before the end', function() {
            actual = [1,2,3].every(function() { return false; });
            expect(actual).toBeFalsy();
        });

        it('should return after 3 elements', function() {
            testSubject.every(function(obj, index) {
                actual[index] = obj;
                numberOfRuns += 1;
                if(numberOfRuns == 3) {
                    return false;
                }
                return true;
            });
            expect(actual).toExactlyMatch(expected);
        });
        it('should stop after 3 elements using a context', function() {
            var o = { a: actual };
            testSubject.every(function(obj, index) {
                this.a[index] = obj;
                numberOfRuns += 1;
                if(numberOfRuns == 3) {
                    return false;
                }
                return true;
            }, o);
            expect(actual).toExactlyMatch(expected);
        });

        it('should stop after 3 elements in an array-like object', function() {
            var ts = createArrayLikeFromArray(testSubject);
            Array.prototype.every.call(ts, function(obj, index) {
                actual[index] = obj;
                numberOfRuns += 1;
                if(numberOfRuns == 3) {
                    return false;
                }
                return true;
            });
            expect(actual).toExactlyMatch(expected);
        });
        it('should stop after 3 elements in an array-like object using a context', function() {
            var ts = createArrayLikeFromArray(testSubject);
            var o = { a: actual };
            Array.prototype.every.call(ts, function(obj, index) {
                this.a[index] = obj;
                numberOfRuns += 1;
                if(numberOfRuns == 3) {
                    return false;
                }
                return true;
            }, o);
            expect(actual).toExactlyMatch(expected);
        });
    });

    describe('indexOf', function() {
        "use strict";
        var actual, expected, testSubject;

        beforeEach(function() {
            testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0];
            delete testSubject[1];

        });

        it('should find the element', function() {
            expected = 4;
            actual = testSubject.indexOf('hej');
            expect(actual).toEqual(expected);
        });
        it('should not find the element', function() {
            expected = -1;
            actual = testSubject.indexOf('mus');
            expect(actual).toEqual(expected);
        });
        it('should find undefined as well', function() {
            expected = -1;
            actual = testSubject.indexOf(undefined);
            expect(actual).not.toEqual(expected);
        });
        it('should skip unset indexes', function() {
            expected = 2;
            actual = testSubject.indexOf(undefined);
            expect(actual).toEqual(expected);
        });
        it('should use a strict test', function() {
            actual = testSubject.indexOf(null);
            expect(actual).toEqual(5);

            actual = testSubject.indexOf('2');
            expect(actual).toEqual(-1);
        });
        it('should skip the first if fromIndex is set', function() {
            expect(testSubject.indexOf(2, 2)).toEqual(6);
            expect(testSubject.indexOf(2, 0)).toEqual(0);
            expect(testSubject.indexOf(2, 6)).toEqual(6);
        });
        it('should work with negative fromIndex', function() {
            expect(testSubject.indexOf(2, -3)).toEqual(6);
            expect(testSubject.indexOf(2, -9)).toEqual(0);
        });
        it('should work with fromIndex being greater than the length', function() {
            expect(testSubject.indexOf('hej', 20)).toEqual(-1);
        });
        it('should work with fromIndex being negative and greater than the length', function() {
            expect(testSubject.indexOf('hej', -20)).toEqual(4);
        });

        describe('Array-like', function ArrayLike() {
            var indexOf = Array.prototype.indexOf,
                testAL;
            beforeEach(function beforeEach() {
                testAL = {};
                testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0];
                testSubject.forEach(function (o,i) {
                    testAL[i] = o;
                });
                testAL.length = testSubject.length;
            });
            it('should find the element (array-like)', function() {
                expected = 4;
                actual = indexOf.call(testAL, 'hej');
                expect(actual).toEqual(expected);
            });
            it('should not find the element (array-like)', function() {
                expected = -1;
                actual = indexOf.call(testAL, 'mus');
                expect(actual).toEqual(expected);
            });
            it('should find undefined as well (array-like)', function() {
                expected = -1;
                actual = indexOf.call(testAL, undefined);
                expect(actual).not.toEqual(expected);
            });
            it('should skip unset indexes (array-like)', function() {
                expected = 2;
                actual = indexOf.call(testAL, undefined);
                expect(actual).toEqual(expected);
            });
            it('should use a strict test (array-like)', function() {
                actual = Array.prototype.indexOf.call(testAL, null);
                expect(actual).toEqual(5);

                actual = Array.prototype.indexOf.call(testAL, '2');
                expect(actual).toEqual(-1);
            });
            it('should skip the first if fromIndex is set (array-like)', function() {
                expect(indexOf.call(testAL, 2, 2)).toEqual(6);
                expect(indexOf.call(testAL, 2, 0)).toEqual(0);
                expect(indexOf.call(testAL, 2, 6)).toEqual(6);
            });
            it('should work with negative fromIndex (array-like)', function() {
                expect(indexOf.call(testAL, 2, -3)).toEqual(6);
                expect(indexOf.call(testAL, 2, -9)).toEqual(0);
            });
            it('should work with fromIndex being greater than the length (array-like)', function() {
                expect(indexOf.call(testAL, 'hej', 20)).toEqual(-1);
            });
            it('should work with fromIndex being negative and greater than the length (array-like)', function() {
                expect(indexOf.call(testAL, 'hej', -20)).toEqual(4);
            });
        });
    });
    describe('lastIndexOf', function() {
        "use strict";
        var actual, expected, testSubject, testAL;

        beforeEach(function() {
            testSubject = [2, 3, undefined, true, 'hej', null, 2, 3, false, 0];
            delete testSubject[1];
            delete testSubject[7];
        });
        describe('Array', function() {
            it('should find the element', function() {
                expected = 4;
                actual = testSubject.lastIndexOf('hej');
                expect(actual).toEqual(expected);
            });
            it('should not find the element', function() {
                expected = -1;
                actual = testSubject.lastIndexOf('mus');
                expect(actual).toEqual(expected);
            });
            it('should find undefined as well', function() {
                expected = -1;
                actual = testSubject.lastIndexOf(undefined);
                expect(actual).not.toEqual(expected);
            });
            it('should skip unset indexes', function() {
                expected = 2;
                actual = testSubject.lastIndexOf(undefined);
                expect(actual).toEqual(expected);
            });
            it('should use a strict test', function() {
                actual = testSubject.lastIndexOf(null);
                expect(actual).toEqual(5);

                actual = testSubject.lastIndexOf('2');
                expect(actual).toEqual(-1);
            });
            it('should skip the first if fromIndex is set', function() {
                expect(testSubject.lastIndexOf(2, 2)).toEqual(0);
                expect(testSubject.lastIndexOf(2, 0)).toEqual(0);
                expect(testSubject.lastIndexOf(2, 6)).toEqual(6);
            });
            it('should work with negative fromIndex', function() {
                expect(testSubject.lastIndexOf(2, -3)).toEqual(6);
                expect(testSubject.lastIndexOf(2, -9)).toEqual(0);
            });
            it('should work with fromIndex being greater than the length', function() {
                expect(testSubject.lastIndexOf(2, 20)).toEqual(6);
            });
            it('should work with fromIndex being negative and greater than the length', function() {
                expect(testSubject.lastIndexOf(2, -20)).toEqual(-1);
            });
        });

        describe('Array like', function() {
            var lastIndexOf = Array.prototype.lastIndexOf,
                testAL;
            beforeEach(function() {
                testAL = {};
                testSubject.forEach(function (o,i) {
                    testAL[i] = o;
                });
                testAL.length = testSubject.length;
            });
            it('should find the element (array-like)', function() {
                expected = 4;
                actual = lastIndexOf.call(testAL, 'hej');
                expect(actual).toEqual(expected);
            });
            it('should not find the element (array-like)', function() {
                expected = -1;
                actual = lastIndexOf.call(testAL, 'mus');
                expect(actual).toEqual(expected);
            });
            it('should find undefined as well (array-like)', function() {
                expected = -1;
                actual = lastIndexOf.call(testAL, undefined);
                expect(actual).not.toEqual(expected);
            });
            it('should skip unset indexes (array-like)', function() {
                expected = 2;
                actual = lastIndexOf.call(testAL, undefined);
                expect(actual).toEqual(expected);
            });
            it('should use a strict test (array-like)', function() {
                actual = lastIndexOf.call(testAL, null);
                expect(actual).toEqual(5);

                actual = lastIndexOf.call(testAL, '2');
                expect(actual).toEqual(-1);
            });
            it('should skip the first if fromIndex is set', function() {
                expect(lastIndexOf.call(testAL, 2, 2)).toEqual(0);
                expect(lastIndexOf.call(testAL, 2, 0)).toEqual(0);
                expect(lastIndexOf.call(testAL, 2, 6)).toEqual(6);
            });
            it('should work with negative fromIndex', function() {
                expect(lastIndexOf.call(testAL, 2, -3)).toEqual(6);
                expect(lastIndexOf.call(testAL, 2, -9)).toEqual(0);
            });
            it('should work with fromIndex being greater than the length', function() {
                expect(lastIndexOf.call(testAL, 2, 20)).toEqual(6);
            });
            it('should work with fromIndex being negative and greater than the length', function() {
                expect(lastIndexOf.call(testAL, 2, -20)).toEqual(-1);
            });
        });
    });

    describe('filter', function() {
        var filteredArray,
            callback = function callback(o, i, arr) {
                return (
                    i != 3 && i != 5
                );
            };

        beforeEach(function() {
            testSubject = [2, 3, undefined, true, 'hej', 3, null, false, 0];
            delete testSubject[1];
            filteredArray = [2, undefined, 'hej', null, false, 0];
        });
        describe('Array object', function() {

            it('should call the callback with the proper arguments', function() {
                var callback = jasmine.createSpy('callback'),
                    arr = ['1'];
                arr.filter(callback);
                expect(callback).toHaveBeenCalledWith('1', 0, arr);
            });
            it('should not affect elements added to the array after it has begun', function() {
                var arr = [1,2,3],
                    i = 0;
                arr.filter(function(a) {
                    i++;
                    if(i <= 4) {
                        arr.push(a+3);
                    }
                    return true;
                });
                expect(arr).toEqual([1,2,3,4,5,6]);
                expect(i).toBe(3);
            });
            it('should skip non-set values', function() {
                var passedValues = {};
                testSubject = [1,2,3,4];
                delete testSubject[1];
                testSubject.filter(function(o, i) {
                    passedValues[i] = o;
                    return true;
                });
                expect(passedValues).toExactlyMatch(testSubject);
            });
            it('should pass the right context to the filter', function() {
                var passedValues = {};
                testSubject = [1,2,3,4];
                delete testSubject[1];
                testSubject.filter(function(o, i) {
                    this[i] = o;
                    return true;
                }, passedValues);
                expect(passedValues).toExactlyMatch(testSubject);
            });
            it('should set the right context when given none', function() {
                var context;
                [1].filter(function() {context = this;});
                expect(context).toBe(function() {return this}.call());
            });
            it('should remove only the values for which the callback returns false', function() {
                var result = testSubject.filter(callback);
                expect(result).toExactlyMatch(filteredArray);
            });
            it('should leave the original array untouched', function() {
                var copy = testSubject.slice();
                testSubject.filter(callback);
                expect(testSubject).toExactlyMatch(copy);
            });
            it('should not be affected by same-index mutation', function () {
                var results = [1, 2, 3]
                .filter(function (value, index, array) {
                    array[index] = 'a';
                    return true;
                });
                expect(results).toEqual([1, 2, 3]);
            });
        });
        describe('Array like', function() {
            beforeEach(function() {
                testSubject = createArrayLikeFromArray(testSubject);
            });
            it('should call the callback with the proper arguments', function() {
                var callback = jasmine.createSpy('callback'),
                    arr = createArrayLikeFromArray(['1']);
                Array.prototype.filter.call(arr, callback);
                expect(callback).toHaveBeenCalledWith('1', 0, arr);
            });
            it('should not affect elements added to the array after it has begun', function() {
                var arr = createArrayLikeFromArray([1,2,3]),
                    i = 0;
                Array.prototype.filter.call(arr, function(a) {
                    i++;
                    if(i <= 4) {
                        arr[i+2] = a+3;
                    }
                    return true;
                });
                delete arr.length;
                expect(arr).toExactlyMatch([1,2,3,4,5,6]);
                expect(i).toBe(3);
            });
            it('should skip non-set values', function() {
                var passedValues = {};
                testSubject = createArrayLikeFromArray([1,2,3,4]);
                delete testSubject[1];
                Array.prototype.filter.call(testSubject, function(o, i) {
                    passedValues[i] = o;
                    return true;
                });
                delete testSubject.length;
                expect(passedValues).toExactlyMatch(testSubject);
            });
            it('should set the right context when given none', function() {
                var context;
                Array.prototype.filter.call(createArrayLikeFromArray([1]), function() {context = this;}, undefined);
                expect(context).toBe(function() {return this}.call());
            });
            it('should pass the right context to the filter', function() {
                var passedValues = {};
                testSubject = createArrayLikeFromArray([1,2,3,4]);
                delete testSubject[1];
                Array.prototype.filter.call(testSubject, function(o, i) {
                    this[i] = o;
                    return true;
                }, passedValues);
                delete testSubject.length;
                expect(passedValues).toExactlyMatch(testSubject);
            });
            it('should remove only the values for which the callback returns false', function() {
                var result = Array.prototype.filter.call(testSubject, callback);
                expect(result).toExactlyMatch(filteredArray);
            });
            it('should leave the original array untouched', function() {
                var copy = createArrayLikeFromArray(testSubject);
                Array.prototype.filter.call(testSubject, callback);
                expect(testSubject).toExactlyMatch(copy);
            });
        });
    });
    describe('map', function() {
        var callback;
        beforeEach(function() {
            var i = 0;
            callback = function() {
                return i++;
            };
        });
        describe('Array object', function() {
            it('should call callback with the right parameters', function() {
                var callback = jasmine.createSpy('callback'),
                    array = [1];
                array.map(callback);
                expect(callback).toHaveBeenCalledWith(1, 0, array);
            });
            it('should set the context correctly', function() {
                var context = {};
                testSubject.map(function(o,i) {
                    this[i] = o;
                }, context);
                expect(context).toExactlyMatch(testSubject);
            });
            it('should set the right context when given none', function() {
                var context;
                [1].map(function() {context = this;});
                expect(context).toBe(function() {return this}.call());
            });
            it('should not change the array it is called on', function() {
                var copy = testSubject.slice();
                testSubject.map(callback);
                expect(testSubject).toExactlyMatch(copy);
            });
            it('should only run for the number of objects in the array when it started', function() {
                var arr = [1,2,3],
                    i = 0;
                arr.map(function(o) {
                    arr.push(o+3);
                    i++;
                    return o;
                });
                expect(arr).toExactlyMatch([1,2,3,4,5,6]);
                expect(i).toBe(3);
            });
            it('should properly translate the values as according to the callback', function() {
                var result = testSubject.map(callback),
                    expected = [0,0,1,2,3,4,5,6];
                delete expected[1];
                expect(result).toExactlyMatch(expected);
            });
            it('should skip non-existing values', function() {
                var array = [1,2,3,4],
                    i = 0;
                delete array[2];
                array.map(function() {
                    i++;
                });
                expect(i).toBe(3);
            });
        });
        describe('Array-like', function() {
            beforeEach(function() {
                testSubject = createArrayLikeFromArray(testSubject);
            });
            it('should call callback with the right parameters', function() {
                var callback = jasmine.createSpy('callback'),
                    array = createArrayLikeFromArray([1]);
                Array.prototype.map.call(array, callback);
                expect(callback).toHaveBeenCalledWith(1, 0, array);
            });
            it('should set the context correctly', function() {
                var context = {};
                Array.prototype.map.call(testSubject, function(o,i) {
                    this[i] = o;
                }, context);
                delete testSubject.length;
                expect(context).toExactlyMatch(testSubject);
            });
            it('should set the right context when given none', function() {
                var context;
                Array.prototype.map.call(createArrayLikeFromArray([1]), function() {context = this;});
                expect(context).toBe(function() {return this}.call());
            });
            it('should not change the array it is called on', function() {
                var copy = createArrayLikeFromArray(testSubject);
                Array.prototype.map.call(testSubject, callback);
                expect(testSubject).toExactlyMatch(copy);
            });
            it('should only run for the number of objects in the array when it started', function() {
                var arr = createArrayLikeFromArray([1,2,3]),
                    i = 0;
                Array.prototype.map.call(arr, function(o) {
                    Array.prototype.push.call(arr, o+3);
                    i++;
                    return o;
                });
                delete arr.length;
                expect(arr).toExactlyMatch([1,2,3,4,5,6]);
                expect(i).toBe(3);
            });
            it('should properly translate the values as according to the callback', function() {
                var result = Array.prototype.map.call(testSubject, callback),
                    expected = [0,0,1,2,3,4,5,6];
                delete expected[1];
                expect(result).toExactlyMatch(expected);
            });
            it('should skip non-existing values', function() {
                var array = createArrayLikeFromArray([1,2,3,4]),
                    i = 0;
                delete array[2];
                Array.prototype.map.call(array, function() {
                    i++;
                });
                expect(i).toBe(3);
            });
        });
    });

    describe('reduce', function() {
        beforeEach(function() {
            testSubject = [1,2,3];
        });

        describe('Array', function() {
            it('should pass the correct arguments to the callback', function() {
                var spy = jasmine.createSpy().andReturn(0);
                testSubject.reduce(spy);
                expect(spy.calls[0].args).toExactlyMatch([1, 2, 1, testSubject]);
            });
            it('should start with the right initialValue', function() {
                var spy = jasmine.createSpy().andReturn(0);
                testSubject.reduce(spy, 0);
                expect(spy.calls[0].args).toExactlyMatch([0, 1, 0, testSubject]);
            });
            it('should not affect elements added to the array after it has begun', function() {
                var arr = [1,2,3],
                    i = 0;
                arr.reduce(function(a, b) {
                    i++;
                    if(i <= 4) {
                        arr.push(a+3);
                    };
                    return b;
                });
                expect(arr).toEqual([1,2,3,4,5]);
                expect(i).toBe(2);
            });
            it('should work as expected for empty arrays', function() {
                var spy = jasmine.createSpy();
                expect(function() {
                    [].reduce(spy);
                }).toThrow();
                expect(spy).not.toHaveBeenCalled();
            });
            it('should throw correctly if no callback is given', function() {
                expect(function() {
                    testSubject.reduce();
                }).toThrow();
            });
            it('should return the expected result', function() {
                expect(testSubject.reduce(function(a,b) {
                    return (a||'').toString()+(b||'').toString();
                })).toEqual(testSubject.join(''));
            });
            it('should not directly affect the passed array', function() {
                var copy = testSubject.slice();
                testSubject.reduce(function(a,b) {
                    return a+b;
                });
                expect(testSubject).toEqual(copy);
            });
            it('should skip non-set values', function() {
                delete testSubject[1];
                var visited = {};
                testSubject.reduce(function(a,b) {
                    if(a)
                        visited[a] = true;
                    if(b)
                        visited[b] = true;
                    return 0;
                });

                expect(visited).toEqual({ '1': true, '3': true });
            });
            /*it('should have the right length', function() {
                expect(testSubject.reduce.length).toBe(1);
            });*/
        });
        describe('Array-like objects', function() {
            beforeEach(function() {
                testSubject = createArrayLikeFromArray(testSubject);
                testSubject.reduce = Array.prototype.reduce;
            });
            it('should pass the correct arguments to the callback', function() {
                var spy = jasmine.createSpy().andReturn(0);
                testSubject.reduce(spy);
                expect(spy.calls[0].args).toExactlyMatch([1, 2, 1, testSubject]);
            });
            it('should start with the right initialValue', function() {
                var spy = jasmine.createSpy().andReturn(0);
                testSubject.reduce(spy, 0);
                expect(spy.calls[0].args).toExactlyMatch([0, 1, 0, testSubject]);
            });
            it('should not affect elements added to the array after it has begun', function() {
                var arr = createArrayLikeFromArray([1,2,3]),
                    i = 0;
                Array.prototype.reduce.call(arr, function(a, b) {
                    i++;
                    if(i <= 4) {
                        arr[i+2] = a+3;
                    };
                    return b;
                });
                expect(arr).toEqual({
                    0: 1,
                    1: 2,
                    2: 3,
                    3: 4,
                    4: 5,
                    length: 3
                });
                expect(i).toBe(2);
            });
            it('should work as expected for empty arrays', function() {
                var spy = jasmine.createSpy();
                expect(function() {
                    Array.prototype.reduce.call({length: 0}, spy);
                }).toThrow();
                expect(spy).not.toHaveBeenCalled();
            });
            it('should throw correctly if no callback is given', function() {
                expect(function() {
                    testSubject.reduce();
                }).toThrow();
            });
            it('should return the expected result', function() {
                expect(testSubject.reduce(function(a,b) {
                    return (a||'').toString()+(b||'').toString();
                })).toEqual('123');
            });
            it('should not directly affect the passed array', function() {
                var copy = createArrayLikeFromArray(testSubject);
                testSubject.reduce(function(a,b) {
                    return a+b;
                });
                delete(testSubject.reduce);
                expect(testSubject).toEqual(copy);
            });
            it('should skip non-set values', function() {
                delete testSubject[1];
                var visited = {};
                testSubject.reduce(function(a,b) {
                    if(a)
                        visited[a] = true;
                    if(b)
                        visited[b] = true;
                    return 0;
                });

                expect(visited).toEqual({ '1': true, '3': true });
            });
            /*it('should have the right length', function() {
                expect(testSubject.reduce.length).toBe(1);
            });*/
        });
    });
    describe('reduceRight', function() {
        beforeEach(function() {
            testSubject = [1,2,3];
        });

        describe('Array', function() {
            it('should pass the correct arguments to the callback', function() {
                var spy = jasmine.createSpy().andReturn(0);
                testSubject.reduceRight(spy);
                expect(spy.calls[0].args).toExactlyMatch([3, 2, 1, testSubject]);
            });
            it('should start with the right initialValue', function() {
                var spy = jasmine.createSpy().andReturn(0);
                testSubject.reduceRight(spy, 0);
                expect(spy.calls[0].args).toExactlyMatch([0, 3, 2, testSubject]);
            });
            it('should not affect elements added to the array after it has begun', function() {
                var arr = [1,2,3],
                    i = 0;
                arr.reduceRight(function(a, b) {
                    i++;
                    if(i <= 4) {
                        arr.push(a+3);
                    };
                    return b;
                });
                expect(arr).toEqual([1,2,3,6,5]);
                expect(i).toBe(2);
            });
            it('should work as expected for empty arrays', function() {
                var spy = jasmine.createSpy();
                expect(function() {
                    [].reduceRight(spy);
                }).toThrow();
                expect(spy).not.toHaveBeenCalled();
            });
            it('should throw correctly if no callback is given', function() {
                expect(function() {
                    testSubject.reduceRight();
                }).toThrow();
            });
            it('should return the expected result', function() {
                expect(testSubject.reduceRight(function(a,b) {
                    return (a||'').toString()+(b||'').toString();
                })).toEqual('321');
            });
            it('should not directly affect the passed array', function() {
                var copy = testSubject.slice();
                testSubject.reduceRight(function(a,b) {
                    return a+b;
                });
                expect(testSubject).toEqual(copy);
            });
            it('should skip non-set values', function() {
                delete testSubject[1];
                var visited = {};
                testSubject.reduceRight(function(a,b) {
                    if(a)
                        visited[a] = true;
                    if(b)
                        visited[b] = true;
                    return 0;
                });

                expect(visited).toEqual({ '1': true, '3': true });
            });
            /*it('should have the right length', function() {
                expect(testSubject.reduceRight.length).toBe(1);
            });*/
        });
        describe('Array-like objects', function() {
            beforeEach(function() {
                testSubject = createArrayLikeFromArray(testSubject);
                testSubject.reduceRight = Array.prototype.reduceRight;
            });
            it('should pass the correct arguments to the callback', function() {
                var spy = jasmine.createSpy().andReturn(0);
                testSubject.reduceRight(spy);
                expect(spy.calls[0].args).toExactlyMatch([3, 2, 1, testSubject]);
            });
            it('should start with the right initialValue', function() {
                var spy = jasmine.createSpy().andReturn(0);
                testSubject.reduceRight(spy, 0);
                expect(spy.calls[0].args).toExactlyMatch([0, 3, 2, testSubject]);
            });
            it('should not affect elements added to the array after it has begun', function() {
                var arr = createArrayLikeFromArray([1,2,3]),
                    i = 0;
                Array.prototype.reduceRight.call(arr, function(a, b) {
                    i++;
                    if(i <= 4) {
                        arr[i+2] = a+3;
                    };
                    return b;
                });
                expect(arr).toEqual({
                    0: 1,
                    1: 2,
                    2: 3,
                    3: 6,
                    4: 5,
                    length: 3 // does not get updated on property assignment
                });
                expect(i).toBe(2);
            });
            it('should work as expected for empty arrays', function() {
                var spy = jasmine.createSpy();
                expect(function() {
                    Array.prototype.reduceRight.call({length:0}, spy);
                }).toThrow();
                expect(spy).not.toHaveBeenCalled();
            });
            it('should throw correctly if no callback is given', function() {
                expect(function() {
                    testSubject.reduceRight();
                }).toThrow();
            });
            it('should return the expected result', function() {
                expect(testSubject.reduceRight(function(a,b) {
                    return (a||'').toString()+(b||'').toString();
                })).toEqual('321');
            });
            it('should not directly affect the passed array', function() {
                var copy = createArrayLikeFromArray(testSubject);
                testSubject.reduceRight(function(a,b) {
                    return a+b;
                });
                delete(testSubject.reduceRight);
                expect(testSubject).toEqual(copy);
            });
            it('should skip non-set values', function() {
                delete testSubject[1];
                var visited = {};
                testSubject.reduceRight(function(a,b) {
                    if(a)
                        visited[a] = true;
                    if(b)
                        visited[b] = true;
                    return 0;
                });

                expect(visited).toEqual({ '1': true, '3': true });
            });
            /*it('should have the right length', function() {
                expect(testSubject.reduceRight.length).toBe(1);
            });*/
        });
    });

	describe('find', function() {
        "use strict";
        var actual, expected, testSubject, index;

        beforeEach(function() {
			index = void 0;
            testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0];
            delete testSubject[1];

        });

        it('should find the element', function() {
            expected = 'hej';
            actual = testSubject.find(function(item){ return item === expected });
            expect(actual).toEqual(expected);
        });
        it('should not find the element', function() {
            expected = void 0;
            actual = testSubject.find(function(item){ return item === -1 });
            expect(actual).toEqual(expected);
        });
        it('should find undefined as well', function() {
            expected = void 0;
            actual = testSubject.find(function(item){ return item === expected });
            expect(actual).toEqual(expected);
        });
        it('should skip unset indexes', function() {
            expected = void 0;
            actual = testSubject.find(function(item, ind){ return item === expected ? ((index = ind), true) : false });
            expect(actual).toEqual(expected);
			expect(index).toEqual(2);
        });

        describe('Array-like', function ArrayLike() {
            var find = Array.prototype.find,
                testAL;
            beforeEach(function beforeEach() {
				index = void 0;
                testAL = {};
                testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0];
                testSubject.forEach(function (o,i) {
                    testAL[i] = o;
                });
                testAL.length = testSubject.length;
            });

			it('should find the element (array-like)', function() {
				expected = 'hej';
				actual = find.call(testAL, function(item){ return item === expected });
				expect(actual).toEqual(expected);
			});
			it('should not find the element (array-like)', function() {
				expected = void 0;
				actual = find.call(testAL, function(item){ return item === -1 });
				expect(actual).toEqual(expected);
			});
			it('should find undefined as well (array-like)', function() {
				expected = void 0;
				actual = find.call(testAL, function(item){ return item === expected });
				expect(actual).toEqual(expected);
			});
			it('should skip unset indexes (array-like)', function() {
				expected = void 0;
				actual = find.call(testAL, function(item, ind){ return item === expected ? ((index = ind), true) : false });
				expect(actual).toEqual(expected);
				expect(index).toEqual(2);
			});
        });
    });

	describe('findIndex', function() {
        "use strict";
        var actual, expected, testSubject, index;

        beforeEach(function() {
			index = void 0;
            testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0];
            delete testSubject[1];

        });

        it('should find the element', function() {
            expected = 4;
            actual = testSubject.findIndex(function(item){ return item === 'hej' });
            expect(actual).toEqual(expected);
        });
        it('should not find the element', function() {
            expected = -1;
            actual = testSubject.findIndex(function(item){ return item === -1 });
            expect(actual).toEqual(expected);
        });
        it('should find undefined as well and should skip unset indexes', function() {
            expected = 2;
            actual = testSubject.findIndex(function(item){ return item === void 0 });
            expect(actual).toEqual(expected);
        });

        describe('Array-like', function ArrayLike() {
            var findIndex = Array.prototype.findIndex,
                testAL;
            beforeEach(function beforeEach() {
				index = void 0;
                testAL = {};
                testSubject = [2, 3, undefined, true, 'hej', null, 2, false, 0];
                testSubject.forEach(function (o,i) {
                    testAL[i] = o;
                });
                testAL.length = testSubject.length;
            });

			it('should find the element (array-like)', function() {
				expected = 4;
				actual = findIndex.call(testAL, function(item){ return item === 'hej' });
				expect(actual).toEqual(expected);
			});
			it('should not find the element (array-like)', function() {
				expected = -1;
				actual = findIndex.call(testAL, function(item){ return item === -1 });
				expect(actual).toEqual(expected);
			});
			it('should find undefined as well (array-like)', function() {
				expected = 2;
				actual = findIndex.call(testAL, function(item){ return item === void 0 });
				expect(actual).toEqual(expected);
			});
        });
    });

    describe('Array.isArray', function () {
        it('should work for Array', function () {
            var ret = Array.isArray([]);

            expect(ret).toBe(true);
        });

        it('should fail for other objects', function () {
            var objects = [
                "someString",
                true,
                false,
                42,
                0,
                {},
                Object.create(null),
                /foo/,
                arguments,
                document.getElementsByTagName("div")
            ];

            objects.forEach(function (v) {
                expect(Array.isArray(v)).toBe(false);
            });
        });
    });

	// ES6

    describe("Array.of", function() {
        it("returns Array: type of Array.of(0, 1) is '[object Array]'", function()
		{
			expect(Object.prototype.toString.call(Array.of(0, 1))).toEqual('[object Array]');
		})

		it("converting a variable number of argument to array: 'Array.of(0, 1) are equal [0, 1]'", function()
		{
			expect(Array.of(0, 1)).toEqual([0, 1]);
		})
    });

    describe("Array.from", function() {
        it("returns Array: type of Array.from('01') is '[object Array]'", function()
		{
			expect(Object.prototype.toString.call(Array.from('01'))).toBe('[object Array]');
		})

		it("converting a string to array: Array.from('01') is '[0, 1]'", function()
		{
			expect(Array.from('01')).toEqual(['0', '1']);
		})

		it('array from arguments: Array.from(arguments) converted to [0, 1]', function()
		{
			expect(function(){return Array.from(arguments);}(0, 1)).toEqual([0, 1]);
		})

		it('[ callback [ value ] ]', function()
		{
			expect(Array.from('12', function(value) {return value;})).toEqual(['1','2']);
		})

		it('[ callback [ index ] ]', function()
		{
			expect(Array.from('12', function(value, index) {return index;})).toEqual([0,1]);
		})

		it('[ callback [ object ] ]', function()
		{
			expect(Array.from('12', function(value, index, object) {return object;})).toEqual(['12','12']);
		})

		it('[ callback [ value, index ] ]', function()
		{
			expect(Array.from('12', function(value, index) {return value + index;})).toEqual(['10','21']);
		})

		it('[ callback [ value, index, object ] ]', function()
		{
			expect(Array.from('12', function(value, index, object) {return value + index + object;})).toEqual(['1012','2112']);
		})

		it('[callback, context ] #1', function()
		{
			var object = {0: 10, 1: 20};

			expect(Array.from('01', function(value) {return this[value];}, object)).toEqual([10,20]);
		})

		it('[callback, context ] #2', function()
		{
			var object = {0: 10, 1: 20};

			expect(Array.from([0, 1], function(value) {return this[value];}, object)).toEqual([10,20]);
		})

		it('empty string value', function()
		{
			expect(Array.from('')).toExactlyMatch([]);
		})

		it('Boolean', function()
		{
			expect(Array.from(true)).toExactlyMatch([]);
		})

		it('Object', function()
		{
			expect(Array.from({})).toExactlyMatch([]);
		})

		it('Array-like object', function()
		{
			expect(Array.from({0: 5, 1: 6, length: 2})).toEqual([5,6]);
		})
    });
});


#import <Cocoa/Cocoa.h>

@class TimerOne;
@class TimerTwo;

@interface FineGrainedLoggingAppDelegate : NSObject <NSApplicationDelegate>
{
    TimerOne *timerOne;
    TimerTwo *timerTwo;

    NSWindow *__unsafe_unretained window;
}

@property (unsafe_unretained) IBOutlet NSWindow *window;

@end


// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "windows.h"
#define STRINGIFY_VALUE(x) STRINGIFY(x)
#define STRINGIFY(x) #x

// @TODO: These values must be replaced during a Jenkins build.
#define RADEON_GPU_ANALYZER_MAJOR_VERSION 0
#define RADEON_GPU_ANALYZER_MINOR_VERSION 0
#define RADEON_GPU_ANALYZER_BUILD_NUMBER 0
#define RADEON_GPU_ANALYZER_REVISION_NUMBER 0
#define RADEON_GPU_ANALYZER_VERSION_STRING STRINGIFY_VALUE(RADEON_GPU_ANALYZER_MAJOR_VERSION) "." STRINGIFY_VALUE(RADEON_GPU_ANALYZER_MINOR_VERSION) "." STRINGIFY_VALUE(RADEON_GPU_ANALYZER_REVISION_NUMBER) "." STRINGIFY_VALUE(RADEON_GPU_ANALYZER_BUILD_NUMBER)

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32

/////////////////////////////////////////////////////////////////////////////
//
// Version
//

VS_VERSION_INFO VERSIONINFO
 FILEVERSION RADEON_GPU_ANALYZER_MAJOR_VERSION, RADEON_GPU_ANALYZER_MINOR_VERSION, RADEON_GPU_ANALYZER_REVISION_NUMBER, RADEON_GPU_ANALYZER_BUILD_NUMBER
 PRODUCTVERSION  RADEON_GPU_ANALYZER_MAJOR_VERSION, RADEON_GPU_ANALYZER_MINOR_VERSION, RADEON_GPU_ANALYZER_REVISION_NUMBER, RADEON_GPU_ANALYZER_BUILD_NUMBER
 FILEFLAGSMASK 0x17L
#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L
#endif
 FILEOS 0x4L
 FILETYPE 0x1L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904b0"
        BEGIN
            VALUE "CompanyName", "Advanced Micro Devices, Inc."
            VALUE "FileDescription", " Radeon GPU Analyzer CLI"
            VALUE "FileVersion", RADEON_GPU_ANALYZER_VERSION_STRING
            VALUE "InternalName", "RadeonGPUAnalyzerCLI"
            VALUE "OriginalFilename", "rga" ".exe"
            VALUE "LegalCopyright", "Copyright (C) 2020 Advanced Micro Devices, Inc."
            VALUE "ProductName", "Radeon GPU Analyzer CLI"
            VALUE "ProductVersion", RADEON_GPU_ANALYZER_VERSION_STRING
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200
    END
END

#endif    // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////


// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Minimal copy of x/sys/unix so the cpu package can make a
// system call on AIX without depending on x/sys/unix.
// (See golang.org/issue/32102)

// +build aix,ppc64
// +build !gccgo

package cpu

import (
	"syscall"
	"unsafe"
)

//go:cgo_import_dynamic libc_getsystemcfg getsystemcfg "libc.a/shr_64.o"

//go:linkname libc_getsystemcfg libc_getsystemcfg

type syscallFunc uintptr

var libc_getsystemcfg syscallFunc

type errno = syscall.Errno

// Implemented in runtime/syscall_aix.go.
func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err errno)
func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err errno)

func callgetsystemcfg(label int) (r1 uintptr, e1 errno) {
	r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_getsystemcfg)), 1, uintptr(label), 0, 0, 0, 0, 0)
	return
}


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>com.ctc.wstx.sr (Woodstox 6.2.0 API)</title>
<meta name="date" content="2020-04-25">
<link rel="stylesheet" type="text/css" href="../../../../stylesheet.css" title="Style">

com.ctc.wstx.sr

Interfaces

InputProblemReporter

NsDefaultProvider

ReaderCreator

StreamReaderImpl

Classes

AttributeCollector

BasicStreamReader

CompactNsContext

ElemAttrs

ElemCallback

InputElementStack

StreamScanner

TypedStreamReader

ValidatingStreamReader


# frozen_string_literal: true

module Alchemy
  module Admin
    class EssenceFilesController < Alchemy::Admin::BaseController
      authorize_resource class: Alchemy::EssenceFile

      before_action :load_essence_file, only: [:edit, :update]

      helper "Alchemy::Admin::Contents"

      def edit
        @content = @essence_file.content
      end

      def update
        @essence_file.update(essence_file_params)
      end

      # Assigns file, but does not saves it.
      #
      # When the user saves the element the content gets updated as well.
      #
      def assign
        @content = Content.find_by(id: params[:content_id])
        @attachment = Attachment.find_by(id: params[:attachment_id])
        @content.essence.attachment = @attachment

        # We need to update timestamp here because we don't save yet,
        # but the cache needs to be get invalid.
        @content.touch
      end

      private

      def essence_file_params
        params.require(:essence_file).permit(:title, :css_class, :link_text)
      end

      def load_essence_file
        @essence_file = EssenceFile.find(params[:id])
      end
    end
  end
end


/*
 * Copyright 2015, Cyril Bur, IBM Corp.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *
 * This test attempts to see if the VMX registers change across preemption.
 * Two things should be noted here a) The check_vmx function in asm only checks
 * the non volatile registers as it is reused from the syscall test b) There is
 * no way to be sure preemption happened so this test just uses many threads
 * and a long wait. As such, a successful test doesn't mean much but a failure
 * is bad.
 */

#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>

#include "utils.h"

/* Time to wait for workers to get preempted (seconds) */
#define PREEMPT_TIME 20
/*
 * Factor by which to multiply number of online CPUs for total number of
 * worker threads
 */
#define THREAD_FACTOR 8

__thread vector int varray[] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10,11,12},
	{13,14,15,16},{17,18,19,20},{21,22,23,24},
	{25,26,27,28},{29,30,31,32},{33,34,35,36},
	{37,38,39,40},{41,42,43,44},{45,46,47,48}};

int threads_starting;
int running;

extern void preempt_vmx(vector int *varray, int *threads_starting, int *running);

void *preempt_vmx_c(void *p)
{
	int i, j;
	srand(pthread_self());
	for (i = 0; i < 12; i++)
		for (j = 0; j < 4; j++)
			varray[i][j] = rand();

	/* Test fails if it ever returns */
	preempt_vmx(varray, &threads_starting, &running);
	return p;
}

int test_preempt_vmx(void)
{
	int i, rc, threads;
	pthread_t *tids;

	threads = sysconf(_SC_NPROCESSORS_ONLN) * THREAD_FACTOR;
	tids = malloc(threads * sizeof(pthread_t));
	FAIL_IF(!tids);

	running = true;
	threads_starting = threads;
	for (i = 0; i < threads; i++) {
		rc = pthread_create(&tids[i], NULL, preempt_vmx_c, NULL);
		FAIL_IF(rc);
	}

	setbuf(stdout, NULL);
	/* Not really nessesary but nice to wait for every thread to start */
	printf("\tWaiting for all workers to start...");
	while(threads_starting)
		asm volatile("": : :"memory");
	printf("done\n");

	printf("\tWaiting for %d seconds to let some workers get preempted...", PREEMPT_TIME);
	sleep(PREEMPT_TIME);
	printf("done\n");

	printf("\tStopping workers...");
	/*
	 * Working are checking this value every loop. In preempt_vmx 'cmpwi r5,0; bne 2b'.
	 * r5 will have loaded the value of running.
	 */
	running = 0;
	for (i = 0; i < threads; i++) {
		void *rc_p;
		pthread_join(tids[i], &rc_p);

		/*
		 * Harness will say the fail was here, look at why preempt_vmx
		 * returned
		 */
		if ((long) rc_p)
			printf("oops\n");
		FAIL_IF((long) rc_p);
	}
	printf("done\n");

	return 0;
}

int main(int argc, char *argv[])
{
	return test_harness(test_preempt_vmx, "vmx_preempt");
}


/**
 *    Copyright 2013, Big Switch Networks, Inc.
 *
 *    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.
 **/

package net.floodlightcontroller.core.web;

import java.util.concurrent.ConcurrentHashMap;

import org.restlet.data.Status;
import org.restlet.resource.Post;
import org.restlet.resource.ServerResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.floodlightcontroller.core.IOFMessageFilterManagerService;

public class PacketTraceResource extends ServerResource {
    protected static Logger log = LoggerFactory.getLogger(PacketTraceResource.class);

    public static class FilterParameters {

        protected String sessionId = null;
        protected String mac = null;
        protected Integer period = null;
        protected String direction = null;
        protected String output = null;

        public String getSessionId() {
            return sessionId;
        }
        public void setSessionId(String sessionId) {
            this.sessionId = sessionId;
        }
        public String getMac() {
            return mac;
        }
        public void setMac(String mac) {
            this.mac = mac;
        }
        public Integer getPeriod() {
            return period;
        }
        public void setPeriod(Integer period) {
            this.period = period;
        }
        public String getDirection() {
            return direction;
        }
        public void setDirection(String direction) {
            this.direction = direction;
        }
        public String getOutput() {
            return output;
        }
        public void setOutput(String output) {
            this.output = output;
        }

        public String toString() {
            return "SessionID: " + sessionId +
                   "\tmac" + mac +
                   "\tperiod" + period +
                   "\tdirection" + direction +
                   "\toutput" + output;
        }
    }

    public static class PacketTraceOutput {
        protected String sessionId = null;

        public String getSessionId() {
            return sessionId;
        }

        public void setSessionId(String sessionId) {
            this.sessionId = sessionId;
        }
    }

    @Post("json")
    public PacketTraceOutput packettrace(FilterParameters fp) {

        ConcurrentHashMap <String,String> filter = new ConcurrentHashMap<String,String> ();
        String sid = null;
        PacketTraceOutput output = new PacketTraceOutput();
        IOFMessageFilterManagerService manager =
                (IOFMessageFilterManagerService)getContext()
                    .getAttributes().
                        get(IOFMessageFilterManagerService.class.getCanonicalName());

        if (manager == null) {
            sid = null;
            setStatus(Status.SERVER_ERROR_SERVICE_UNAVAILABLE);
        }

        if (fp.getSessionId() != null) {
            filter.put("sessionId", fp.getSessionId());
        }
        if (fp.getMac() != null) {
            filter.put("mac", fp.getMac());
        }
        if (fp.getDirection() != null) {
            filter.put("direction", fp.getDirection());
        }

        if (filter.isEmpty()) {
            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
        } else {
            if (log.isDebugEnabled()) {
                log.debug ("Call setupFilter: sid:{} filter:{}, period:{}",
                           new Object[] {fp.getSessionId(), filter,
                                         fp.getPeriod()*1000});
            }
            sid = manager.setupFilter(fp.getSessionId(), filter,
                                      fp.getPeriod()*1000);
            output.setSessionId(sid);
            setStatus(Status.SUCCESS_OK);
        }

        return output;
    }
}


/**
 * Hebrew translation for bootstrap-datepicker
 * Sagie Maoz <sagie@maoz.info>
 */
;(function($){
  $.fn.datepicker.dates['he'] = {
      days: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת", "ראשון"],
      daysShort: ["א", "ב", "ג", "ד", "ה", "ו", "ש", "א"],
      daysMin: ["א", "ב", "ג", "ד", "ה", "ו", "ש", "א"],
      months: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"],
      monthsShort: ["ינו", "פבר", "מרץ", "אפר", "מאי", "יונ", "יול", "אוג", "ספט", "אוק", "נוב", "דצמ"],
      today: "היום",
      rtl: true
  };
}(jQuery));


<snippet>
    <content><![CDATA[setTitleLabelForState(${1:label}, ${2:state})]]></content>
    <tabTrigger>setTitleLabelForState(label, state)</tabTrigger>
    <scope>source.lua</scope>
    <description>ControlButton</description>
</snippet>


/*
 * Copyright (c) 2000 Nordic Semiconductor ASA
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright notice, this list
 *      of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
 *      integrated circuit in a product or a software update for such product, must reproduce
 *      the above copyright notice, this list of conditions and the following disclaimer in
 *      the documentation and/or other materials provided with the distribution.
 *
 *   3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
 *      used to endorse or promote products derived from this software without specific prior
 *      written permission.
 *
 *   4. This software, with or without modification, must only be used with a
 *      Nordic Semiconductor ASA integrated circuit.
 *
 *   5. Any software provided in binary or object form under this license must not be reverse
 *      engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

 /**
  @defgroup nrf_error SoftDevice Global Error Codes
  @{

  @brief Global Error definitions
*/

/* Header guard */
#ifndef NRF_ERROR_H__
#define NRF_ERROR_H__

#ifdef __cplusplus
extern "C" {
#endif

/** @defgroup NRF_ERRORS_BASE Error Codes Base number definitions
 * @{ */
#define NRF_ERROR_BASE_NUM      (0x0)       ///< Global error base
#define NRF_ERROR_SDM_BASE_NUM  (0x1000)    ///< SDM error base
#define NRF_ERROR_SOC_BASE_NUM  (0x2000)    ///< SoC error base
#define NRF_ERROR_STK_BASE_NUM  (0x3000)    ///< STK error base
/** @} */

#define NRF_SUCCESS                           (NRF_ERROR_BASE_NUM + 0)  ///< Successful command
#define NRF_ERROR_SVC_HANDLER_MISSING         (NRF_ERROR_BASE_NUM + 1)  ///< SVC handler is missing
#define NRF_ERROR_SOFTDEVICE_NOT_ENABLED      (NRF_ERROR_BASE_NUM + 2)  ///< SoftDevice has not been enabled
#define NRF_ERROR_INTERNAL                    (NRF_ERROR_BASE_NUM + 3)  ///< Internal Error
#define NRF_ERROR_NO_MEM                      (NRF_ERROR_BASE_NUM + 4)  ///< No Memory for operation
#define NRF_ERROR_NOT_FOUND                   (NRF_ERROR_BASE_NUM + 5)  ///< Not found
#define NRF_ERROR_NOT_SUPPORTED               (NRF_ERROR_BASE_NUM + 6)  ///< Not supported
#define NRF_ERROR_INVALID_PARAM               (NRF_ERROR_BASE_NUM + 7)  ///< Invalid Parameter
#define NRF_ERROR_INVALID_STATE               (NRF_ERROR_BASE_NUM + 8)  ///< Invalid state, operation disallowed in this state
#define NRF_ERROR_INVALID_LENGTH              (NRF_ERROR_BASE_NUM + 9)  ///< Invalid Length
#define NRF_ERROR_INVALID_FLAGS               (NRF_ERROR_BASE_NUM + 10) ///< Invalid Flags
#define NRF_ERROR_INVALID_DATA                (NRF_ERROR_BASE_NUM + 11) ///< Invalid Data
#define NRF_ERROR_DATA_SIZE                   (NRF_ERROR_BASE_NUM + 12) ///< Invalid Data size
#define NRF_ERROR_TIMEOUT                     (NRF_ERROR_BASE_NUM + 13) ///< Operation timed out
#define NRF_ERROR_NULL                        (NRF_ERROR_BASE_NUM + 14) ///< Null Pointer
#define NRF_ERROR_FORBIDDEN                   (NRF_ERROR_BASE_NUM + 15) ///< Forbidden Operation
#define NRF_ERROR_INVALID_ADDR                (NRF_ERROR_BASE_NUM + 16) ///< Bad Memory Address
#define NRF_ERROR_BUSY                        (NRF_ERROR_BASE_NUM + 17) ///< Busy
#define NRF_ERROR_CONN_COUNT                  (NRF_ERROR_BASE_NUM + 18) ///< Maximum connection count exceeded.
#define NRF_ERROR_RESOURCES                   (NRF_ERROR_BASE_NUM + 19) ///< Not enough resources for operation

#ifdef __cplusplus
}
#endif
#endif // NRF_ERROR_H__

/**
  @}
*/


//
//  TWTRSession.h
//
//  Copyright (c) 2015 Twitter. All rights reserved.
//

#import <TwitterCore/TWTRAuthConfig.h>
#import <TwitterCore/TWTRAuthSession.h>
#import <TwitterCore/TWTRGuestSession.h>

@class TWTRSession;

NS_ASSUME_NONNULL_BEGIN

/**
 *  Completion block called when user login succeeds or fails.
 *
 *  @param session Contains the OAuth tokens and minimal information associated with the logged in user or nil.
 *  @param error   Error that will be non nil if the authentication request failed.
 */
typedef void (^TWTRLogInCompletion)(TWTRSession * _Nullable session,  NSError * _Nullable error);

/**
 *  TWTRSession represents a user's session authenticated with the Twitter API.
 */
@interface TWTRSession : NSObject <TWTRAuthSession>

/**
 *  The authorization token.
 */
@property (nonatomic, copy, readonly) NSString *authToken;
/**
 *  The authorization token secret.
 */
@property (nonatomic, copy, readonly) NSString *authTokenSecret;
/**
 *  The username associated with the access token.
 */
@property (nonatomic, copy, readonly) NSString *userName;
/**
 *  The user ID associated with the access token.
 */
@property (nonatomic, copy, readonly) NSString *userID;

/**
 *  Returns an `TWTRSession` object initialized by copying the values from the dictionary or nil if the dictionary is missing.
 *
 *  @param sessionDictionary (required) The dictionary received after successfull authentication from Twitter OAuth.
 */
- (instancetype)initWithSessionDictionary:(NSDictionary *)sessionDictionary;

/**
 *  Returns an `TWTRSession` object initialized by copying the given tokens and user info.
 *
 *  @param authToken       (required) The authorization token for the session
 *  @param authTokenSecret (required) The authorization token secret for the session
 *  @param userName        (required) The username for the user associated with the session.
 *  @param userID          (required) The unique ID for the user associated with the session.
 *
 *  @return A `TWTRSession` object initialized with the provided parameters.
 */
- (instancetype)initWithAuthToken:(NSString *)authToken authTokenSecret:(NSString *)authTokenSecret userName:(NSString *)userName userID:(NSString *)userID NS_DESIGNATED_INITIALIZER;

/**
 *  Unavailable. Use -initWithSessionDictionary: instead.
 */
- (instancetype)init NS_UNAVAILABLE;

@end

NS_ASSUME_NONNULL_END


<!-- Please prefix your title with one of the following:

[WIP] - If the pull request is not finalized
[MRG] - If you are ready to have this PR looked at by a project maintainer

-->

# Description

Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. List any dependencies
that are required for this change.

Fixes #(issue)

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation change

# How Has This Been Tested?

Please describe the tests that you ran to verify your changes.
Provide instructions so we can reproduce. Please also list any relevant details
for your test configuration

- [ ] Test A
- [ ] Test B

# Checklist:

- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes


DROP TABLE IF EXISTS t;
SET SESSION TOKUDB_DISABLE_SLOW_ALTER=ON;
CREATE TABLE t (a VARCHAR(100), b VARCHAR(100)) ENGINE=Tokudb;
INSERT INTO t VALUES ('hi','there'),('you','people');
SELECT * FROM t;
a	b
hi	there
you	people
ALTER TABLE t CHANGE COLUMN a a VARCHAR(101);
SHOW CREATE TABLE t;
Table	Create Table
t	CREATE TABLE `t` (
  `a` varchar(101) DEFAULT NULL,
  `b` varchar(100) DEFAULT NULL
) ENGINE=TokuDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
ALTER TABLE t CHANGE COLUMN a a VARCHAR(200);
SHOW CREATE TABLE t;
Table	Create Table
t	CREATE TABLE `t` (
  `a` varchar(200) DEFAULT NULL,
  `b` varchar(100) DEFAULT NULL
) ENGINE=TokuDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
SELECT * FROM t;
a	b
hi	there
you	people
DROP TABLE t;
CREATE TABLE t (i INT, a VARCHAR(100), b VARCHAR(100)) ENGINE=Tokudb;
INSERT INTO t VALUES (1, 'hi','there'),(2, 'you','people');
SELECT * FROM t;
i	a	b
1	hi	there
2	you	people
ALTER TABLE t CHANGE COLUMN a a VARCHAR(101);
SHOW CREATE TABLE t;
Table	Create Table
t	CREATE TABLE `t` (
  `i` int DEFAULT NULL,
  `a` varchar(101) DEFAULT NULL,
  `b` varchar(100) DEFAULT NULL
) ENGINE=TokuDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
ALTER TABLE t CHANGE COLUMN a a VARCHAR(200);
SHOW CREATE TABLE t;
Table	Create Table
t	CREATE TABLE `t` (
  `i` int DEFAULT NULL,
  `a` varchar(200) DEFAULT NULL,
  `b` varchar(100) DEFAULT NULL
) ENGINE=TokuDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
SELECT * FROM t;
i	a	b
1	hi	there
2	you	people
DROP TABLE t;


// This is brl/bseg/brip/brip_subpix_convolution.h
#ifndef brip_subpix_convolution_h
#define brip_subpix_convolution_h
//:
// \file
// \brief A class to compute subpixel convolutions by using shifted operators
// \author Amir Tamrakar
// \date 9 Sept 2006
//
// \verbatim
//  Modifications
//   <none yet>
// \endverbatim

#include <vil/algo/vil_correlate_1d.h>
#include <vil/algo/vil_correlate_2d.h>
#include <vil/vil_transpose.h>
#include <vgl/vgl_point_2d.h>

//: Convolve an image(src_im) with shifted kernels to compute the value at the subpixel positions
//  The subpixel values are computed at 1/2^N intervals in each dimension. e.g., N=0: regular
//  convolution, N=1: compute at mid-pixel locations, N=2: compute at quarter pixel locations
//
// I'm using vil_correlate_2d_at_pt to evaluate the dot_product at pixel/subpixel locations
// dest_im is resized to [2^N*src_im.ni() x 2^N*src_im.nj()]
//
template <class srcT, class destT, class kernelT, class accumT>
inline void brip_subpix_convolve_2d(const vil_image_view<srcT>& src_im,
                                    vil_image_view<destT>& dest_im,
                                    kernelT kernel, accumT ac,
                                    int N)
{
  int two_pow_N = 1 << N;

  //the portion of the src_image that can be used for the convolution
  int src_ni = 1+src_im.ni()-kernel.ni(); assert(src_ni >= 0);
  int src_nj = 1+src_im.nj()-kernel.nj(); assert(src_nj >= 0);

  // filtered image will be 2^N time larger than the original
  int dest_ni = two_pow_N*src_im.ni(); assert(dest_ni >= 0);
  int dest_nj = two_pow_N*src_im.nj(); assert(dest_nj >= 0);

  //resize the dest image to this size
  dest_im.set_size(dest_ni,dest_nj,1);
  dest_im.fill(0);

  //determine the step sizes
  std::ptrdiff_t s_istep = src_im.istep(), s_jstep = src_im.jstep();
  std::ptrdiff_t s_pstep = src_im.planestep();
  std::ptrdiff_t d_istep = dest_im.istep(), d_jstep = dest_im.jstep();

  // filter with shifted versions of the original filter
  // we need 2^(2N) convolutions to completely compute it

  for (int shift_i=0; shift_i<two_pow_N; shift_i++){
    for (int shift_j=0; shift_j<two_pow_N; shift_j++){
      //instantiate a shifted kernel
      kernel.recompute_kernel(double(shift_i)/two_pow_N, double(shift_j)/two_pow_N);

      //invert kernel to use correlation code
      //kernelT inv_kernel = vil_flip_ud(vil_flip_lr(kernel));

      //***********************************************************
      //Now convolve the image with this kernel

      //Put the result in the right place on the destination image
      //depending on the current shifts

      //***********************************************************

      //Select the first pixel on the src image that is valid
      int khs = (kernel.ni()-1)/2;
      const srcT*  src_row  = src_im.top_left_ptr();

      //select the corresponding first pixel on the dest image
      destT* dest_row = dest_im.top_left_ptr()+(shift_i+two_pow_N*khs)+(shift_j+two_pow_N*khs)*d_jstep;

      for (int j=0;j<src_nj;++j,src_row+=s_jstep,dest_row+=two_pow_N*d_jstep)
      {
        const srcT* sp = src_row;
        destT* dp = dest_row;
        for (int i=0;i<src_ni;++i, sp += s_istep, dp += two_pow_N*d_istep){
          // Correlate at src(i,j)
          *dp = (destT)vil_correlate_2d_at_pt(sp, s_istep, s_jstep, s_pstep, kernel, ac);
        }
      }
    }
  }
}

//: Convolve the image with the given kernel at the given subpixel locations (pts) only
template <class srcT, class kernelT, class accumT>
inline void brip_subpix_convolve_2d(const vil_image_view<srcT>& src_im,
                                    const std::vector<vgl_point_2d<accumT> >& pts,
                                    std::vector<accumT>& res,
                                    kernelT kernel, accumT ac,
                                    int /*N*/)
{
  res.resize(pts.size());
  int khs = (kernel.ni()-1)/2;

  //determine the step sizes for the src_image
  std::ptrdiff_t s_istep = src_im.istep(), s_jstep = src_im.jstep(), s_pstep = src_im.planestep();
  //for each subpixel point, we need to create a new kernel shifted to that location
  for (unsigned i=0; i<pts.size(); i++)
  {
    //determine closest integer coordinates of the current point
    int x = (int) std::floor(pts[i].x());
    int y = (int) std::floor(pts[i].y());

    //assert(x>=khs && y>=khs && x<src_im.ni()-khs && y<src_im.nj()-khs);

    if (x<khs || y<khs){
      res[i]=0;
      continue;
    }

    //determine the shift from it
    double dx = pts[i].x() - x;
    double dy = pts[i].y() - y;

    //instantiate a shifted kernel for this point
    kernel.recompute_kernel(dx, dy);

    //invert kernel to use correlation code
    //kernelT inv_kernel = vil_flip_ud(vil_flip_lr(kernel));

    //Select the first pixel on the src image that is valid

    const srcT*  sp  = src_im.top_left_ptr() + (x-khs)*s_istep + (y-khs)*s_jstep;

    // Correlate at src(x,y)
    res[i] = (accumT)vil_correlate_2d_at_pt(sp, s_istep, s_jstep, s_pstep, kernel, ac);
  }
}

//: Convolve the image with the given kernel at the given subpixel locations (pts) only at the given orientation
template <class srcT, class kernelT, class accumT>
inline void brip_subpix_convolve_2d(const vil_image_view<srcT>& src_im,
                                    const std::vector<vgl_point_2d<accumT> >& pts,
                                    const std::vector<accumT>& thetas,
                                    std::vector<accumT>& res,
                                    kernelT kernel, accumT ac,
                                    int /*N*/)
{
  res.resize(pts.size());
  int khs = (kernel.ni()-1)/2;

  //determine the step sizes for the src_image
  std::ptrdiff_t s_istep = src_im.istep(), s_jstep = src_im.jstep(), s_pstep = src_im.planestep();
  //for each subpixel point, we need to create a new kernel shifted to that location
  for (unsigned i=0; i<pts.size(); i++)
  {
    //determine closest integer coordinates of the current point
    int x = (int) std::floor(pts[i].x());
    int y = (int) std::floor(pts[i].y());

    //assert(x>=khs && y>=khs && x<src_im.ni()-khs && y<src_im.nj()-khs);

    if (x<khs || y<khs){
      res[i]=0;
      continue;
    }

    //determine the shift from it
    double dx = pts[i].x() - x;
    double dy = pts[i].y() - y;

    //instantiate a shifted kernel for this point
    kernel.recompute_kernel(dx, dy, thetas[i]);

    //invert kernel to use correlation code
    //kernelT inv_kernel = vil_flip_ud(vil_flip_lr(kernel));

    //Select the first pixel on the src image that is valid

    const srcT*  sp  = src_im.top_left_ptr() + (x-khs)*s_istep + (y-khs)*s_jstep;

    // Correlate at src(x,y)
    res[i] = (accumT)vil_correlate_2d_at_pt(sp, s_istep, s_jstep, s_pstep, kernel, ac);
  }
}

//: Convolve an image(src_im) with shifted kernels to compute the value at the subpixel positions
//  The subpixel values are computed at 1/2^N intervals in each dimension. e.g., N=0: regular
//  convolution, N=1: compute at mid-pixel locations, N=2: compute at quarter pixel locations
//
//  To speed up the convolution, I'm performing 2 independent convolutions with 1-d kernels.
//  dest_im is resized to [2^N*src_im.ni() x 2^N*src_im.nj()]
//
template <class srcT, class destT, class kernelT, class accumT>
inline void brip_subpix_convolve_2d_sep(const vil_image_view<srcT>& src_im,
                                        vil_image_view<destT>& dest_im,
                                        kernelT kernel, accumT ac,
                                        int N)
{
  int two_pow_N = 1 << N;

  //the portion of the src_image that can be used for the convolution
  int src_ni = src_im.ni(); assert(src_ni >= 0);
  int src_nj = src_im.nj(); assert(src_nj >= 0);

  // filtered image will be 2^N time larger than the original
  int dest_ni = two_pow_N*src_im.ni(); assert(dest_ni >= 0);
  int dest_nj = two_pow_N*src_im.nj(); assert(dest_nj >= 0);

  //resize the dest image to this size
  dest_im.set_size(dest_ni,dest_nj,1);
  dest_im.fill(0);

  //determine the step sizes
  std::ptrdiff_t s_istep = src_im.istep(), s_jstep = src_im.jstep();
  std::ptrdiff_t d_istep = dest_im.istep(), d_jstep = dest_im.jstep();

  // filter with shifted versions of the original filter
  // we need 2^(2N) convolutions to completely compute it

  for (int shift_i=0; shift_i<two_pow_N; shift_i++){
    for (int shift_j=0; shift_j<two_pow_N; shift_j++){

      // Generate filter: instantiate a shifted kernel
      kernel.recompute_kernel(double(shift_i)/two_pow_N, double(shift_j)/two_pow_N);

      //determine the half width of the kernel
      int khs = kernel.khs;

      // Apply 1D convolution along i direction using the K_x filter
      vil_image_view<destT> work_im;
      vil_correlate_1d(src_im, work_im, &kernel.K_x[khs], -khs, khs,
                       ac, vil_convolve_no_extend, vil_convolve_no_extend);

      // Apply 1D convolution along j direction by applying K_y filter to its transpose
      vil_image_view<destT> work_im2;
      work_im2.set_size(src_im.ni(), src_im.nj(), src_im.nplanes());

      vil_image_view<destT> work_im_t = vil_transpose(work_im);
      vil_image_view<destT> work_im2_t = vil_transpose(work_im2);

      vil_correlate_1d(work_im_t, work_im2_t,
                       &kernel.K_y[khs], -khs, khs,
                       ac, vil_convolve_no_extend, vil_convolve_no_extend);

      //compose this convolution, at the sub pixel location, into the larger dest image
      destT*  src_row  = work_im2.top_left_ptr();

      //select the corresponding first pixel on the dest image
      destT* dest_row = dest_im.top_left_ptr()+(shift_i)+(shift_j)*d_jstep;

      for (int j=0;j<src_nj;++j, src_row+=s_jstep, dest_row+=two_pow_N*d_jstep)
      {
        const destT* sp = src_row;
        destT* dp = dest_row;
        for (int i=0;i<src_ni;++i, sp += s_istep, dp += two_pow_N*d_istep){
          *dp = (destT) *sp;
        }
      }
    }
  }
}

#endif // brip_subpix_convolution_h


fileFormatVersion: 2
guid: 57a7ab354e6564aec8b2acea065c6736
TextureImporter:
  fileIDToRecycleName: {}
  serializedVersion: 2
  mipmaps:
    mipMapMode: 0
    enableMipMap: 0
    linearTexture: 0
    correctGamma: 0
    fadeOut: 0
    borderMipMap: 0
    mipMapFadeDistanceStart: 1
    mipMapFadeDistanceEnd: 3
  bumpmap:
    convertToNormalMap: 0
    externalNormalMap: 0
    heightScale: .25
    normalMapFilter: 0
  isReadable: 0
  grayScaleToAlpha: 0
  generateCubemap: 0
  cubemapConvolution: 0
  cubemapConvolutionSteps: 8
  cubemapConvolutionExponent: 1.5
  seamlessCubemap: 0
  textureFormat: -1
  maxTextureSize: 128
  textureSettings:
    filterMode: -1
    aniso: -1
    mipBias: -1
    wrapMode: 1
  nPOTScale: 0
  lightmap: 0
  rGBM: 0
  compressionQuality: 50
  allowsAlphaSplitting: 0
  spriteMode: 1
  spriteExtrude: 1
  spriteMeshType: 1
  alignment: 0
  spritePivot: {x: .5, y: .5}
  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
  spritePixelsToUnits: 100
  alphaIsTransparency: 1
  textureType: 8
  buildTargetSettings: []
  spriteSheet:
    sprites: []
  spritePackingTag: ui
  userData:
  assetBundleName:
  assetBundleVariant:


/*
Problem Statement :
Add two numbers using bitwise operators
(i.e without using arithmetic operators)
*/

#include <stdio.h>

// iterative function
int bitwiseAddition(int n, int m)
{
    while (m != 0)
    {
        int carry = n & m;
        n = n ^ m;
        m = carry << 1;
    }
    return n;
}

// recursive function
int bitwiseAdditionRecursive(int n, int m)
{
    if (m == 0)
        return n;
    else
    {
        int carry = n & m;
        return bitwiseAdditionRecursive(n ^ m, carry << 1);
    }
}

int main()
{
    int a, b;
    printf("Enter two numbers: ");
    scanf("%d %d", &a, &b);

    printf("\nBitwise addition using iterative function : %d", bitwiseAddition(a, b));
    printf("\nBitwise addition using recursive function : %d", bitwiseAdditionRecursive(a, b));
    return 0;
}

/*
Enter two numbers : 3 5

Bitwise addition using iterative function : 8
Bitwise addition using recursive function : 8
*/