blob: d4d85c9d33ee21876294be958ac6c16e41a20c99 [file] [log] [blame]
// Copyright (c) Facebook, Inc. and its affiliates.
// All rights reserved.
//
// Copyright 2019 Google LLC
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree.
#pragma once
#include <stdint.h>
#include <limits.h>
// The code below is adapted from Google's gemmlowp library.
// It is only used in XNNPACK unit tests and comparative benchmarks, but not the library itself.
//
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
inline static int32_t gemmlowp_scalar_vqrdmulh_s32(int32_t a, int32_t b)
{
const bool overflow = a == b && a == INT32_MIN;
const int64_t ab_64 = (int64_t) a * (int64_t) b;
const int32_t nudge = (a ^ b) >= 0 ? INT32_C(0x40000000) : -INT32_C(0x3FFFFFFF);
const int32_t ab_x2_high32 = (int32_t) ((ab_64 + nudge) / INT64_C(0x80000000));
return overflow ? INT32_MAX : ab_x2_high32;
}
inline static int32_t gemmlowp_scalar_rdivbypo2_s32(int32_t x, int exponent)
{
const int32_t mask = ((1 << exponent) - 1);
const int32_t remainder = x & mask;
const int32_t threshold = (mask >> 1) + (int32_t) (x < 0);
return asr_s32(x, exponent) + (int32_t) (remainder > threshold);
}